WPF 实现展示反应盘、者试剂仓控件

WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织

      由于微信群人数太多入群请添加小编微信号

(yanjinhuawechat)或(W_Feng_aiQ)入群

(需备注WPF开发者

  PS:有更好的方式欢迎推荐。

01

代码如下

一、创建 DrawingControl.cs 继承 ListBox代码如下。

f13061b04c03f9476657db5f8320799c.png

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;namespace WPFDevelopers.Controls
{[TemplatePart(Name = _PartInnerName, Type = typeof(Border))]//[TemplatePart(Name = _PartDrawingPanelName, Type=typeof(DrawingPanel))]//[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(DrawingElement))]public class DrawingControl : ListBox{static DrawingControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(DrawingControl), new FrameworkPropertyMetadata(typeof(DrawingControl)));}private const string _PartInnerName = "PART_InnerBorder";//private const string _PartDrawingPanelName = "PART_DrawingPanel";public DrawingControl(){Loaded += DrawingControl_Loaded;SizeChanged += DrawingControl_SizeChanged;}protected DrawingPanel _DrawingPanel = default;protected Border _Border = default;public override void OnApplyTemplate(){base.OnApplyTemplate();_Border = GetTemplateChild(_PartInnerName) as Border;// _DrawingPanel = GetTemplateChild(_PartDrawingPanelName) as DrawingPanel;if (_Border == null)throw new Exception($"The {_PartInnerName} is not exist!");}private void DrawingControl_Loaded(object sender, RoutedEventArgs e){//Width = Math.Min(RenderSize.Width, RenderSize.Height);//Height = Width;}private void DrawingControl_SizeChanged(object sender, SizeChangedEventArgs e){var vMin = Math.Min(e.NewSize.Width, e.NewSize.Height);PanelCornerRadius = new CornerRadius(vMin);InnerCornerRadius = new CornerRadius(vMin);//InnerMargin = new Thickness(vMin * Scale);if (_Border != null){_Border.Width = vMin * Scale;_Border.Height = vMin * Scale;}}public double ItemOffset{get { return (double)GetValue(ItemOffsetProperty); }set { SetValue(ItemOffsetProperty, value); }}public static readonly DependencyProperty ItemOffsetProperty =DependencyProperty.Register("ItemOffset", typeof(double), typeof(DrawingControl), new PropertyMetadata(10d));public Brush PanelBackground{get { return (Brush)GetValue(PanelBackgroundProperty); }set { SetValue(PanelBackgroundProperty, value); }}public static readonly DependencyProperty PanelBackgroundProperty =DependencyProperty.Register("PanelBackground", typeof(Brush), typeof(DrawingControl), new PropertyMetadata(default));public Brush PanelBorderBrush{get { return (Brush)GetValue(PanelBorderBrushProperty); }set { SetValue(PanelBorderBrushProperty, value); }}public static readonly DependencyProperty PanelBorderBrushProperty =DependencyProperty.Register("PanelBorderBrush", typeof(Brush), typeof(DrawingControl), new PropertyMetadata(Brushes.Gray));public Thickness PanelBorderThinckness{get { return (Thickness)GetValue(PanelBorderThincknessProperty); }set { SetValue(PanelBorderThincknessProperty, value); }}public static readonly DependencyProperty PanelBorderThincknessProperty =DependencyProperty.Register("PanelBorderThinckness", typeof(Thickness), typeof(DrawingControl), new PropertyMetadata(new Thickness(1d)));public CornerRadius PanelCornerRadius{get { return (CornerRadius)GetValue(PanelCornerRadiusProperty); }set { SetValue(PanelCornerRadiusProperty, value); }}public static readonly DependencyProperty PanelCornerRadiusProperty =DependencyProperty.Register("PanelCornerRadius", typeof(CornerRadius), typeof(DrawingControl), new PropertyMetadata(new CornerRadius(1d)));public DrawingMode PanelDrawingMode{get { return (DrawingMode)GetValue(PanelDrawingModeProperty); }set { SetValue(PanelDrawingModeProperty, value); }}public static readonly DependencyProperty PanelDrawingModeProperty =DependencyProperty.Register("PanelDrawingMode", typeof(DrawingMode), typeof(DrawingControl), new PropertyMetadata(default(DrawingMode)));public double PanelStartAngleOffset{get { return (double)GetValue(PanelStartAngleOffsetProperty); }set { SetValue(PanelStartAngleOffsetProperty, value); }}public static readonly DependencyProperty PanelStartAngleOffsetProperty =DependencyProperty.Register("PanelStartAngleOffset", typeof(double), typeof(DrawingControl), new PropertyMetadata(0d));public string PanelMultipleDescription{get { return (string)GetValue(PanelMultipleDescriptionProperty); }set { SetValue(PanelMultipleDescriptionProperty, value); }}public static readonly DependencyProperty PanelMultipleDescriptionProperty =DependencyProperty.Register("PanelMultipleDescription", typeof(string), typeof(DrawingControl), new PropertyMetadata(default));public double PanelMultipleSpace{get { return (double)GetValue(PanelMultipleSpaceProperty); }set { SetValue(PanelMultipleSpaceProperty, value); }}public static readonly DependencyProperty PanelMultipleSpaceProperty =DependencyProperty.Register("PanelMultipleSpace", typeof(double), typeof(DrawingControl), new PropertyMetadata(0d));public Thickness InnerMargin{get { return (Thickness)GetValue(InnerMarginProperty); }set { SetValue(InnerMarginProperty, value); }}public static readonly DependencyProperty InnerMarginProperty =DependencyProperty.Register("InnerMargin", typeof(Thickness), typeof(DrawingControl), new PropertyMetadata(new Thickness(50d)));public Brush InnerBackground{get { return (Brush)GetValue(InnerBackgroundProperty); }set { SetValue(InnerBackgroundProperty, value); }}public static readonly DependencyProperty InnerBackgroundProperty =DependencyProperty.Register("InnerBackground", typeof(Brush), typeof(DrawingControl), new PropertyMetadata(Brushes.Transparent));public CornerRadius InnerCornerRadius{get { return (CornerRadius)GetValue(InnerCornerRadiusProperty); }set { SetValue(InnerCornerRadiusProperty, value); }}public static readonly DependencyProperty InnerCornerRadiusProperty =DependencyProperty.Register("InnerCornerRadius", typeof(CornerRadius), typeof(DrawingControl), new PropertyMetadata(default));public Thickness InnerBorderThickness{get { return (Thickness)GetValue(InnerBorderThicknessProperty); }set { SetValue(InnerBorderThicknessProperty, value); }}public static readonly DependencyProperty InnerBorderThicknessProperty =DependencyProperty.Register("InnerBorderThickness", typeof(Thickness), typeof(DrawingControl), new PropertyMetadata(new Thickness(1d)));public Brush InnerBorderBrush{get { return (Brush)GetValue(InnerBorderBrushProperty); }set { SetValue(InnerBorderBrushProperty, value); }}public static readonly DependencyProperty InnerBorderBrushProperty =DependencyProperty.Register("InnerBorderBrush", typeof(Brush), typeof(DrawingControl), new PropertyMetadata(Brushes.Gray));public double Scale{get { return (double)GetValue(ScaleProperty); }set { SetValue(ScaleProperty, value); }}public static readonly DependencyProperty ScaleProperty =DependencyProperty.Register("Scale", typeof(double), typeof(DrawingControl), new PropertyMetadata(0.4d, OnScalePropertyChangedCallBack));public object Content{get { return (object)GetValue(ContentProperty); }set { SetValue(ContentProperty, value); }}public static readonly DependencyProperty ContentProperty =DependencyProperty.Register("Content", typeof(object), typeof(DrawingControl), new PropertyMetadata(default));public DataTemplate ContentTemplate{get { return (DataTemplate)GetValue(ContentTemplateProperty); }set { SetValue(ContentTemplateProperty, value); }}public static readonly DependencyProperty ContentTemplateProperty =DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(DrawingControl), new PropertyMetadata(default));public DataTemplateSelector ContentTemplateSelector{get { return (DataTemplateSelector)GetValue(ContentTemplateSelectorProperty); }set { SetValue(ContentTemplateSelectorProperty, value); }}public static readonly DependencyProperty ContentTemplateSelectorProperty =DependencyProperty.Register("ContentTemplateSelector", typeof(DataTemplateSelector), typeof(DrawingControl), new PropertyMetadata(default));public string ContentStringFormat{get { return (string)GetValue(ContentStringFormatProperty); }set { SetValue(ContentStringFormatProperty, value); }}public static readonly DependencyProperty ContentStringFormatProperty =DependencyProperty.Register("ContentStringFormat", typeof(string), typeof(DrawingControl), new PropertyMetadata(default));public string ContentSource{get { return (string)GetValue(ContentSourceProperty); }set { SetValue(ContentSourceProperty, value); }}public static readonly DependencyProperty ContentSourceProperty =DependencyProperty.Register("ContentSource", typeof(string), typeof(DrawingControl), new PropertyMetadata("Content"));private static void OnScalePropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e){if (!(d is DrawingControl drawing))return;//drawing.InnerMargin = new Thickness(vMin * drawing.Scale);if (drawing._Border != null){var vMin = Math.Min(drawing.RenderSize.Width, drawing.RenderSize.Height);drawing._Border.Width = vMin * drawing.Scale;drawing._Border.Height = vMin * drawing.Scale;}}}
}

二、创建 DrawingPanel.cs 继承 Panel代码如下。

f2dfe6beafebfef94c91e3638ddabd25.png

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using WPFDevelopers.Assists;
using WPFDevelopers.Utilities;namespace WPFDevelopers.Controls
{public enum DrawingMode{Left,Right,Top,Bottom,}public class DrawingPanel : Panel{public static readonly DependencyProperty BorderBrushProperty =DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(DrawingPanel), new PropertyMetadata(default, OnRenderPropertyChangedCallBack));public static readonly DependencyProperty BorderThicknessProperty =DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(DrawingPanel), new PropertyMetadata(new Thickness(), OnRenderPropertyChangedCallBack));public static readonly DependencyProperty CornerRadiusProperty =DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(DrawingPanel), new PropertyMetadata(new CornerRadius(), OnRenderPropertyChangedCallBack));public static readonly DependencyProperty OffsetProperty =DependencyProperty.Register("Offset", typeof(double), typeof(DrawingPanel), new PropertyMetadata(0d, OnRenderPropertyChangedCallBack));public static readonly DependencyProperty ModeProperty =DependencyProperty.Register("Mode", typeof(DrawingMode), typeof(DrawingPanel), new PropertyMetadata(default(DrawingMode), OnRenderPropertyChangedCallBack));public static readonly DependencyProperty StartOffsetAngleProperty =DependencyProperty.Register("StartOffsetAngle", typeof(double), typeof(DrawingPanel), new PropertyMetadata(0d, OnRenderPropertyChangedCallBack));public Brush BorderBrush{get { return (Brush)GetValue(BorderBrushProperty); }set { SetValue(BorderBrushProperty, value); }}public Thickness BorderThickness{get { return (Thickness)GetValue(BorderThicknessProperty); }set { SetValue(BorderThicknessProperty, value); }}public CornerRadius CornerRadius{get { return (CornerRadius)GetValue(CornerRadiusProperty); }set { SetValue(CornerRadiusProperty, value); }}public double Offset{get { return (double)GetValue(OffsetProperty); }set { SetValue(OffsetProperty, value); }}public DrawingMode Mode{get { return (DrawingMode)GetValue(ModeProperty); }set { SetValue(ModeProperty, value); }}public double StartOffsetAngle{get { return (double)GetValue(StartOffsetAngleProperty); }set { SetValue(StartOffsetAngleProperty, value); }}public string MultipleArrayDescription{get { return (string)GetValue(MultipleArrayDescriptionProperty); }set { SetValue(MultipleArrayDescriptionProperty, value); }}public static readonly DependencyProperty MultipleArrayDescriptionProperty =DependencyProperty.Register("MultipleArrayDescription", typeof(string), typeof(DrawingPanel), new PropertyMetadata(default, OnRenderPropertyChangedCallBack));public double LayerSpace{get { return (double)GetValue(LayerSpaceProperty); }set { SetValue(LayerSpaceProperty, value); }}public static readonly DependencyProperty LayerSpaceProperty =DependencyProperty.Register("LayerSpace", typeof(double), typeof(DrawingPanel), new PropertyMetadata(5d, OnRenderPropertyChangedCallBack));private List<int> _MultipleArray = default;private static void OnRenderPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e){if (!(d is DrawingPanel drawing))return;drawing.InvalidateVisual();}protected override Size MeasureOverride(Size availableSize){double width = 0;double height = 0;foreach (var child in InternalChildren){if (!(child is UIElement uiElement))continue;uiElement.Measure(availableSize);width = Math.Max(width, uiElement.DesiredSize.Width);height = Math.Max(height, uiElement.DesiredSize.Height);uiElement.RenderSize = new Size(width, height);}if (double.IsPositiveInfinity(availableSize.Width))availableSize.Width = width * 4 + Offset * 2;if (double.IsPositiveInfinity(availableSize.Height))availableSize.Height = height * 4 + Offset * 2;return availableSize;}protected override Size ArrangeOverride(Size finalSize){if (double.IsPositiveInfinity(finalSize.Width)|| double.IsPositiveInfinity(finalSize.Height)|| double.IsNaN(finalSize.Width)|| double.IsNaN(finalSize.Height)|| double.IsNegativeInfinity(finalSize.Width)|| double.IsNegativeInfinity(finalSize.Height))return finalSize;double realValue = Math.Min(finalSize.Width, finalSize.Height);Size desiredSzie = new Size(realValue, realValue);MultipleArrangeOverride();if (IsMuliple())ArrangeOverrideMultiple(realValue);elseArrangeOverrideSingle(realValue);return desiredSzie;}protected override void OnRender(DrawingContext dc){OnRenderBackground(dc);}private bool OnRenderBackground(DrawingContext dc){Thickness border = BorderThickness;Brush borderBrush = BorderBrush;Brush backGround = Background;CornerRadius cornerRadius = CornerRadius;double outerCornerRadius = cornerRadius.TopLeft; // Already validated that all corners have the same radiusbool roundedCorners = !DoubleUtil.IsZero(outerCornerRadius);if (!border.IsZero() && borderBrush != null){Pen pen = new Pen();pen.Brush = borderBrush;pen.Thickness = border.Left;if (borderBrush.IsFrozen)pen.Freeze();double halfThickness;if (border.IsUniform()){halfThickness = pen.Thickness * 0.5;Rect rect = new Rect(new Point(halfThickness, halfThickness), new Point(RenderSize.Width - halfThickness, RenderSize.Height - halfThickness));if (roundedCorners){dc.DrawRoundedRectangle(backGround,pen,rect,outerCornerRadius,outerCornerRadius);}else{dc.DrawRectangle(backGround,pen,rect);}}else{if (DoubleUtil.GreaterThan(border.Left, 0)){halfThickness = pen.Thickness * 0.5;dc.DrawLine(pen,new Point(halfThickness, 0),new Point(halfThickness, RenderSize.Height));}if (DoubleUtil.GreaterThan(border.Right, 0)){halfThickness = pen.Thickness * 0.5;dc.DrawLine(pen,new Point(RenderSize.Width - halfThickness, 0),new Point(RenderSize.Width - halfThickness, RenderSize.Height));}if (DoubleUtil.GreaterThan(border.Top, 0)){halfThickness = pen.Thickness * 0.5;dc.DrawLine(pen,new Point(0, halfThickness),new Point(RenderSize.Width, halfThickness));}if (DoubleUtil.GreaterThan(border.Bottom, 0)){halfThickness = pen.Thickness * 0.5;dc.DrawLine(pen,new Point(0, RenderSize.Height - halfThickness),new Point(RenderSize.Width, RenderSize.Height - halfThickness));}}}else{Rect rect = new Rect(new Point(0, 0), new Point(RenderSize.Width, RenderSize.Height));if (roundedCorners){dc.DrawRoundedRectangle(backGround,null,rect,outerCornerRadius,outerCornerRadius);}else{dc.DrawRectangle(backGround,null,rect);}}return true;}private bool MultipleArrangeOverride(){_MultipleArray?.Clear();_MultipleArray = default;if (string.IsNullOrWhiteSpace(MultipleArrayDescription))return true;_MultipleArray = new List<int>();var vArray = MultipleArrayDescription.Split(',');foreach (var item in vArray){if (string.IsNullOrWhiteSpace(item))continue;if (!int.TryParse(item, out var vResult))continue;if (vResult <= 0)continue;//var v = _MultipleArray.Where(ix => ix == vResult).ToList();//if (v.Count == 0)//_MultipleArray.Add(vResult);_MultipleArray.Add(vResult);}int nCount = 0;foreach (var item in _MultipleArray)nCount += item;if (nCount < InternalChildren.Count)_MultipleArray.Add(InternalChildren.Count - nCount);return true;}private bool ArrangeOverrideSingle(double realValue){var vInternalChildren = InternalChildren;double angle = 360d / vInternalChildren.Count;switch (Mode){case DrawingMode.Left:ArrangeOverride_Left(vInternalChildren, realValue, angle);break;case DrawingMode.Right:ArrangeOverride_Right(vInternalChildren, realValue, angle);break;case DrawingMode.Top:ArrangeOverride_Top(vInternalChildren, realValue, angle);break;case DrawingMode.Bottom:ArrangeOverride_Bottom(vInternalChildren, realValue, angle);break;default:ArrangeOverride_Left(vInternalChildren, realValue, angle);break;}return true;}private bool ArrangeOverride_Left(UIElementCollection internalChildren, double realValue, double angle){if (internalChildren == null || internalChildren.Count <= 0)return false;if (realValue <= 0 || angle <= 0)return false;int index = 0;foreach (var child in internalChildren){index++;if (!(child is UIElement uiElement))continue;if (uiElement.DesiredSize.IsEmpty)continue;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))continue;Point size = new Point(Offset, (realValue - uiElement.DesiredSize.Height) / 2d);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));var vRotateTransform = new RotateTransform(){Angle = angle * (index - 1) + StartOffsetAngle,};var vRealValue = realValue - 2 * Offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Width;uiElement.RenderTransformOrigin = new Point(vRet, 0.5);uiElement.RenderTransform = vRotateTransform;}return true;}private bool ArrangeOverride_Right(UIElementCollection internalChildren, double realValue, double angle){if (internalChildren == null || internalChildren.Count <= 0)return false;if (realValue <= 0 || angle <= 0)return false;int index = 0;foreach (var child in internalChildren){index++;if (!(child is UIElement uiElement))continue;if (uiElement.DesiredSize.IsEmpty)continue;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))continue;Point size = new Point(realValue - Offset - uiElement.DesiredSize.Width, (realValue - uiElement.DesiredSize.Height) / 2d);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));var vRotateTransform = new RotateTransform(){Angle = angle * (index - 1) + StartOffsetAngle,};var vRealValue = realValue - 2 * Offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Width - 1;uiElement.RenderTransformOrigin = new Point(-vRet, 0.5);uiElement.RenderTransform = vRotateTransform;}return true;}private bool ArrangeOverride_Top(UIElementCollection internalChildren, double realValue, double angle){if (internalChildren == null || internalChildren.Count <= 0)return false;if (realValue <= 0 || angle <= 0)return false;int index = 0;foreach (var child in internalChildren){index++;if (!(child is UIElement uiElement))continue;if (uiElement.DesiredSize.IsEmpty)continue;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))continue;Point size = new Point((realValue - uiElement.DesiredSize.Width) / 2d, Offset);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));var vRotateTransform = new RotateTransform(){Angle = angle * (index - 1) + StartOffsetAngle,};var vRealValue = realValue - 2 * Offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Height;uiElement.RenderTransformOrigin = new Point(0.5, vRet);uiElement.RenderTransform = vRotateTransform;}return true;}private bool ArrangeOverride_Bottom(UIElementCollection internalChildren, double realValue, double angle){if (internalChildren == null || internalChildren.Count <= 0)return false;if (realValue <= 0 || angle <= 0)return false;int index = 0;foreach (var child in internalChildren){index++;if (!(child is UIElement uiElement))continue;if (uiElement.DesiredSize.IsEmpty)continue;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))continue;Point size = new Point((realValue - uiElement.DesiredSize.Width) / 2d, realValue - Offset - uiElement.DesiredSize.Height);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));var vRotateTransform = new RotateTransform(){Angle = angle * (index - 1) + StartOffsetAngle,};var vRealValue = realValue - 2 * Offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Height - 1;uiElement.RenderTransformOrigin = new Point(0.5, -vRet);uiElement.RenderTransform = vRotateTransform;}return true;}private bool IsMuliple(){if (_MultipleArray?.Count > 0){int nCount = 0;foreach (var item in _MultipleArray)nCount += item;if (nCount > InternalChildren.Count)return false;return true;}return false;}private bool ArrangeOverrideMultiple(double realValue){double offset = Offset;var vInternalChildren = InternalChildren;int nStartIndex = 0;double lastMaxWidth = 0;double lastMaxHeight = 0;int nLoopIndex = 0;foreach (var item in _MultipleArray){double angle = 360d / item;int nIndex = 0;double maxWidth = 0;double maxHeight = 0;for (int i = nStartIndex; i < nStartIndex + item; ++i){var child = vInternalChildren[i];Size vSize = Size.Empty;switch (Mode){case DrawingMode.Left:{var vOffset = offset + lastMaxWidth + LayerSpace * nLoopIndex;ArrangeOverride_Left(child, nIndex, vOffset, realValue, angle, out vSize);}break;case DrawingMode.Right:{var vOffset = offset + lastMaxWidth + LayerSpace * nLoopIndex;ArrangeOverride_Right(child, nIndex, vOffset, realValue, angle, out vSize);}break;case DrawingMode.Top:{var vOffset = offset + lastMaxHeight + LayerSpace * nLoopIndex;ArrangeOverride_Top(child, nIndex, vOffset, realValue, angle, out vSize);}break;case DrawingMode.Bottom:{var vOffset = offset + lastMaxHeight + LayerSpace * nLoopIndex;ArrangeOverride_Bottom(child, nIndex, vOffset, realValue, angle, out vSize);}break;default:{var vOffset = offset + lastMaxWidth + LayerSpace * nLoopIndex;ArrangeOverride_Left(child, nIndex, vOffset, realValue, angle, out vSize);}break;}maxWidth = Math.Max(maxWidth, vSize.Width);maxHeight = Math.Max(maxHeight, vSize.Height);nIndex++;}lastMaxWidth += maxWidth;lastMaxHeight += maxHeight;nStartIndex += item;nLoopIndex++;}return true;}private bool ArrangeOverride_Left(UIElement uiElement, int index, double offset, double realValue, double angle, out Size desiredSize){desiredSize = Size.Empty;if (realValue <= 0 || angle <= 0)return false;if (uiElement.DesiredSize.IsEmpty)return false;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))return false;Point size = new Point(offset, (realValue - uiElement.DesiredSize.Height) / 2d);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));desiredSize = uiElement.DesiredSize;var vRotateTransform = new RotateTransform(){Angle = angle * index + StartOffsetAngle,};var vRealValue = realValue - 2 * offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Width;uiElement.RenderTransformOrigin = new Point(vRet, 0.5);uiElement.RenderTransform = vRotateTransform;return true;}private bool ArrangeOverride_Right(UIElement uiElement, int index, double offset, double realValue, double angle, out Size desiredSize){desiredSize = Size.Empty;if (realValue <= 0 || angle <= 0)return false;if (uiElement.DesiredSize.IsEmpty)return false;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))return false;Point size = new Point(realValue - offset - uiElement.DesiredSize.Width, (realValue - uiElement.DesiredSize.Height) / 2d);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));desiredSize = uiElement.DesiredSize;var vRotateTransform = new RotateTransform(){Angle = angle * index + StartOffsetAngle,};var vRealValue = realValue - 2 * offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Width - 1;uiElement.RenderTransformOrigin = new Point(-vRet, 0.5);uiElement.RenderTransform = vRotateTransform;return true;}private bool ArrangeOverride_Top(UIElement uiElement, int index, double offset, double realValue, double angle, out Size desiredSize){desiredSize = Size.Empty;if (realValue <= 0 || angle <= 0)return false;if (uiElement.DesiredSize.IsEmpty)return false;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))return false;Point size = new Point((realValue - uiElement.DesiredSize.Width) / 2d, offset);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));desiredSize = uiElement.DesiredSize;var vRotateTransform = new RotateTransform(){Angle = angle * index + StartOffsetAngle,};var vRealValue = realValue - 2 * offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Height;uiElement.RenderTransformOrigin = new Point(0.5, vRet);uiElement.RenderTransform = vRotateTransform;return true;}private bool ArrangeOverride_Bottom(UIElement uiElement, int index, double offset, double realValue, double angle, out Size desiredSize){desiredSize = Size.Empty;if (realValue <= 0 || angle <= 0)return false;if (uiElement.DesiredSize.IsEmpty)return false;if (DoubleUtil.IsZero(uiElement.DesiredSize.Width) || DoubleUtil.IsZero(uiElement.DesiredSize.Height))return false;Point size = new Point((realValue - uiElement.DesiredSize.Width) / 2d, realValue - offset - uiElement.DesiredSize.Height);uiElement.Arrange(new Rect(size, uiElement.DesiredSize));desiredSize = uiElement.DesiredSize;var vRotateTransform = new RotateTransform(){Angle = angle * index + StartOffsetAngle,};var vRealValue = realValue - 2 * offset;if (vRealValue <= 0)return false;var vRet = vRealValue / 2 / uiElement.DesiredSize.Height - 1;uiElement.RenderTransformOrigin = new Point(0.5, -vRet);uiElement.RenderTransform = vRotateTransform;return true;}}
}

三、Drawing.xaml代码如下

787a4009f47e4d2e042b1fa685d58840.png

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="clr-namespace:WPFDevelopers.Controls"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Basic/ControlBasic.xaml"/></ResourceDictionary.MergedDictionaries><Style  x:Key="DrawingControlItem"TargetType="{x:Type ListBoxItem}"BasedOn="{StaticResource ControlBasicStyle}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="ListBoxItem"><Border SnapsToDevicePixels="True"><ContentPresenter /></Border><ControlTemplate.Triggers><Trigger Property="IsSelected"Value="true"><Setter Property="Background"Value="{x:Null}" /></Trigger><Trigger Property="IsEnabled"Value="false"><Setter Property="Foreground"Value="{x:Null}" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style><Style TargetType="controls:DrawingControl" BasedOn="{StaticResource ControlBasicStyle}"><Setter Property="Background" Value="Transparent"/><Setter Property="BorderBrush" Value="{x:Null}"/><Setter Property="BorderThickness" Value="0"/><Setter Property="Foreground" Value="{StaticResource PrimaryTextSolidColorBrush}"/><Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/><Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/><Setter Property="ScrollViewer.CanContentScroll" Value="true"/><Setter Property="ScrollViewer.PanningMode" Value="Both"/><Setter Property="Stylus.IsFlicksEnabled" Value="False"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Padding" Value="0"/><Setter Property="ItemContainerStyle" Value="{StaticResource DrawingControlItem}"/><Setter Property="Margin" Value="0"/><Setter Property="ItemsPanel"><Setter.Value><ItemsPanelTemplate><controls:DrawingPanel x:Name="PART_DrawingPanel" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelBackground, Mode=TwoWay}" CornerRadius="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelCornerRadius, Mode=TwoWay}" BorderThickness="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelBorderThinckness, Mode=TwoWay}"BorderBrush="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelBorderBrush, Mode=TwoWay}"Offset="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=ItemOffset, Mode=TwoWay}"Mode="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelDrawingMode, Mode=TwoWay}"StartOffsetAngle="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelStartAngleOffset, Mode=TwoWay}"MultipleArrayDescription="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelMultipleDescription, Mode=TwoWay}"LayerSpace="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:DrawingControl}, Path=PanelMultipleSpace, Mode=TwoWay}"/></ItemsPanelTemplate></Setter.Value></Setter><!--<Setter Property="ItemContainerStyle" Value="{StaticResource DrawingElementStyle}"/>--><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type controls:DrawingControl}"><Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="0" SnapsToDevicePixels="true"><Grid><ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}"><ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></ScrollViewer><Border x:Name="PART_InnerBorder"VerticalAlignment="Center"HorizontalAlignment="Center"Background="{TemplateBinding InnerBackground}" BorderBrush="{TemplateBinding InnerBorderBrush}"BorderThickness="{TemplateBinding InnerBorderThickness}"CornerRadius="{TemplateBinding InnerCornerRadius}" Padding="3" ><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/></Border></Grid></Border><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="false"><Setter Property="Opacity" Value="0.4"/></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="IsGrouping" Value="true"/></MultiTrigger.Conditions><Setter Property="ScrollViewer.CanContentScroll" Value="false"/></MultiTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style></ResourceDictionary>

四、DrawingExample.xaml代码如下

62e179aa4ef696198f020cb61bc8f335.png

<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.DrawingExample"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"xmlns:wpfdev="https://github.com/yanjinhuagood/WPFDevelopers" xmlns:vm="clr-namespace:WPFDevelopers.Samples.ViewModels"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><UserControl.DataContext><vm:DrawingExampleVM/></UserControl.DataContext><UniformGrid Columns="3" Rows="2"><wpfdev:DrawingControl InnerBackground="{StaticResource SuccessSolidColorBrush}"Content="反应盘"><ListBoxItem Content="盘1"/><ListBoxItem Content="盘2"/><ListBoxItem Content="盘3"/><ListBoxItem Content="盘4"/><ListBoxItem Content="盘5"/></wpfdev:DrawingControl><wpfdev:DrawingControl ItemsSource="{Binding Drawings}"Content="试剂仓"PanelBorderThinckness="0" PanelBackground="#FFF2F2F2" InnerBorderThickness="1" InnerBorderBrush="{StaticResource DangerSolidColorBrush}"InnerBackground="White" PanelDrawingMode="Top"><wpfdev:DrawingControl.ItemTemplate><DataTemplate><!--<Border CornerRadius="5"Width="28" Height="45" BorderThickness="1" BorderBrush="Green"Background="Red"><TextBlock Text="{Binding Number}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Normal"  Foreground="White"/></Border>--><Button Style="{StaticResource DefaultButton}"Content="{Binding Number}"/></DataTemplate></wpfdev:DrawingControl.ItemTemplate></wpfdev:DrawingControl><wpfdev:DrawingControl ItemsSource="{Binding Drawings}"Content="试剂仓"PanelBorderThinckness="0" PanelBackground="#FFF2F2F2" InnerBorderThickness="1" InnerBackground="{StaticResource WarningSolidColorBrush}" PanelDrawingMode="Right"PanelMultipleSpace="10"PanelMultipleDescription="5"><wpfdev:DrawingControl.ItemTemplate><DataTemplate><!--<Border CornerRadius="30" Width="30" Height="30" BorderThickness="1" BorderBrush="Green" Background="Red"><TextBlock Text="{Binding Number}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Normal"  Foreground="White"/></Border>--><CheckBox Content="{Binding Number}"/></DataTemplate></wpfdev:DrawingControl.ItemTemplate></wpfdev:DrawingControl><wpfdev:DrawingControl ItemsSource="{Binding Drawings}"Content="试剂仓"PanelBorderThinckness="0" PanelBackground="#FFF2F2F2" InnerBorderThickness="1" InnerBackground="White" PanelDrawingMode="Bottom"PanelMultipleSpace="2"PanelMultipleDescription="2,3"><wpfdev:DrawingControl.ItemTemplate><DataTemplate><!--<Border CornerRadius="5" Width="28" Height="45" BorderThickness="1" BorderBrush="Green" Background="Red"><TextBlock Text="{Binding Number}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Normal"  Foreground="White"/></Border>--><RadioButton Content="{Binding Number}"/></DataTemplate></wpfdev:DrawingControl.ItemTemplate></wpfdev:DrawingControl><wpfdev:DrawingControl ItemsSource="{Binding Drawings}"Content="试剂仓"PanelBorderThinckness="0" PanelBackground="#FFF2F2F2" InnerBorderThickness="1" InnerBackground="White" PanelDrawingMode="Left"PanelMultipleSpace="0"PanelMultipleDescription="3,3"><wpfdev:DrawingControl.ItemTemplate><DataTemplate><!--<Border CornerRadius="5" Width="28" Height="45" BorderThickness="1" BorderBrush="Green" Background="Red"><TextBlock Text="{Binding Number}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Normal"  Foreground="White"/></Border>--><Button Style="{StaticResource PrimaryButton}" Content="{Binding Number}"/></DataTemplate></wpfdev:DrawingControl.ItemTemplate></wpfdev:DrawingControl></UniformGrid>
</UserControl>

02


效果预览

鸣谢素材提供者 - 吴锋

源码地址如下

github:https://github.com/WPFDevelopersOrg

gitee:https://gitee.com/WPFDevelopersOrg

WPF开发者QQ群: 340500857 

Github:https://github.com/WPFDevelopersOrg

出处:https://www.cnblogs.com/yanjinhua

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载请著名作者 出处 https://github.com/WPFDevelopersOrg

90ba63d1b6def3324e657a069b0bbf68.png

扫一扫关注我们,

5fab7b0d7c4f7570c43363b212af8f21.gif

更多知识早知道!

bd7c2cde568e9eece32881349e4dbe44.gif

点击阅读原文可跳转至源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

向linux内核版本号添加字符/为何有时会自动添加“+”号

转载&#xff1a;http://blog.csdn.net/adaptiver/article/details/7225980 1. 引子 编译2.6.35.7 kernel版本的时候发现&#xff0c;“2.6.35.7“的内核版本编译成功后生成的版本号变成了“2.6.35.7”&#xff0c;为什么后面会多一个加号呢&#xff1f;问题出现在linux的版本…

渣男劈腿,两个女生逼他做出选择,结果......

1 生一个女儿有多重要&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 真实版眼睛瞪得像铜铃&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 地表最强撞衫&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 过年时最怕遇见的人&#xff08;素材…

安卓判断服务器返回的状态码,AppsFlyer返回状态码400

我实现Appsflyer我的样本项目&#xff0c;但是当我运行它&#xff0c;服务器返回错误代码400AppsFlyer返回状态码400I/AppsFlyer_1.18-117182240: response code: 400还有就是我MainActivty.javapublic class MainActivity extends AppCompatActivity {public static final Str…

java多进程、多线程讲解

一、 什么是进程、线程&#xff1f;线程和进程的区别&#xff1f; 1. 进程 当一个程序进入内存运行时&#xff0c;即变成一个进程。进程是处于运行过程中的程序。 进程是操作系统进行资源分配和调度的一个独立单位。 进程的三个特征&#xff1a; 独立性 独立存在的实体&#xf…

fstream实现文件复制(并将文件名小写改成大写)

使用C的fstream类来实现char* filename "C:\\grldr.mbr";//须复制文件路径 int len strlen(filename); while( *(filenamelen-1)!\\){ len--; }//获得文件名 char temp[32]; strcpy(temp,(filenamelen)); for (int i 0; i<s…

AsyncHttpClient的连接池使用逻辑

AsyncHttpClient的连接池结构很简单, NettyConnectionsPool内部重要的几个变量如下 // 连接池, 通过 host 区分不同的池private final ConcurrentHashMap<String, ConcurrentLinkedQueue<IdleChannel>> connectionsPool new ConcurrentHashMap<String, Concurr…

记录一次C#爬虫记录,获取必应图片

起因事情是这样的&#xff0c;我创建了一个仓库&#xff0c;里面有2018年到目前为止每日的必应壁纸&#xff0c;在八月份的时候我看到微软有接口文档&#xff0c;于是写了一个服务&#xff0c;每天早上八点钟会获取必应壁纸&#xff08;目前已经可以作为api来使用了&#xff0c…

word打出计算机图形符号,在word插入符号和特殊符号-word技巧-电脑技巧收藏家

在word插入符号和特殊符号打开“插入”菜单&#xff0c;单击“特殊字符”命令&#xff0c;打开“插入特殊符号”对话框&#xff0c;在这个对话框中有六个选项卡&#xff0c;分别列出了六类不同的特殊符号&#xff1b;从列表中选择要插入的特殊字符&#xff0c;单击“确定”按钮…

Android插件化开发基础之静态代理模式

一 Proxy模式 意图&#xff1a; 为其他对象提供一种代理以控制这个对象的访问。 适用性&#xff1a; l 远程代理&#xff08; Remote Proxy &#xff09;&#xff1a; 为一个对象在不同的地址空间提供局部代表。 l 虚代理&#xff08;Virtual Proxy&#xff09;根据需要创建…

史上最强数学科普!

全世界只有3.14 % 的人关注了爆炸吧知识“中国现代数学之父”华罗庚曾说过宇宙之大&#xff0c;粒子之微火箭之速&#xff0c;化工之巧地球之变&#xff0c;生物之谜日用之繁&#xff0c;无处不用数学回首往昔数学始终伴随我们左右纵横交错的几何、繁琐复杂的运算难以求解的方程…

FastCgi与PHP-fpm之间的关系

我在网上查fastcgi与php-fpm的关系&#xff0c;查了快一周了&#xff0c;基本看了个遍&#xff0c;真是众说纷纭&#xff0c;没一个权威性的定义。网上有的说&#xff0c;fastcgi是一个协议&#xff0c;php-fpm实现了这个协议&#xff1b; 有的说&#xff0c;php-fpm是fastcgi进…

QQ在线联系代码

添加图文模块,标题地址:tencent://message/?uin你的QQ号&Sitemyqq&Menuyes “你的QQ号”就写您自己的Q号 图片地址写:http://wpa.qq.com/pa?p1:你的QQ号:13 “你的QQ号”改为您自己的。“13”为图片样式的序号&#xff0c;可以为1-17。 样式1&#xff1a;样式2&#…

服务器 不支持gbk,解决JS请求服务器gbk文件乱码的问题

JS获取服务器编码格式为gb2312的文件时内容为乱码&#xff0c;ajax网络请求内部使用的是XMLHttpRequest&#xff0c;所以在请求之前需要设置一下编码格式&#xff0c;但是设置xhr.setRequestHeader("accept", "text/csv;charsetgb2312,*/*");没有效果&…

C# 死锁的原理与排查方法详解

01—死锁的原理线程死锁是指由于两个或者多个线程互相持有对方所需要的资源&#xff0c;并且互相等待对方释放资源&#xff0c;导致这些线程都处于等待状态&#xff0c;无法继续执行。如果线程都不主动释放所占有的资源&#xff0c;将产生死锁。如果死锁发生在UI线程&#xff0…

Android之category

CATEGORY_ALTERNATIVE设置这个activity是否可以被认为是用户正在浏览的数据的一个可选择的actionCATEGORY_APP_BROWSER和ACTION_MAIN一起使用&#xff0c;用来启动浏览器应用程序CATEGORY_APP_CALCULATOR和ACTION_MAIN一起使用&#xff0c;用来启动计算器应用程序CATEGORY_APP_…

人生没有对与错,只是选择不同

全世界只有3.14 % 的人关注了爆炸吧知识你用碎片时间学习、赚钱、与时俱进&#xff0c;还是拿来聊天&#xff0c;消遣&#xff0c;刷视频&#xff1f;碎片时间&#xff0c;拉开人生差距&#xff0c;没有对与错&#xff0c;只是选择不同。人生很多地方都有岔路口&#xff0c;很多…

application/x-www-form-urlencoded 与multipart/form-data

为什么上传文件的表单里要加个属性 enctype 上传文件的表单中<form>要加属性enctype"multipart/form-data",很多人只是死记硬背知道上传表单要这么写&#xff0c;知其然而不知其所以然。那到底为什么要添加这个属性呢&#xff1f;它是什么意思呢&#xff1f;它…

学会这些, 让你的服务器远离***影响

介绍:SSH又称Secure Shell, 是linux下常用的远程登陆服务器方式, 其基于SSL加密功能, 相比较ftp, telnet等明文传输协议来说安全等级更高, 在在企业开发环境中被大量使用, 而基于SSH的安全方式鱼龙混杂, 各有春秋. 原因&#xff1a;有一个朋友是做游戏的&#xff0c;他告诉我他…

Android之ActivityManager与Proxy模式的运用

二 Android中ActivityManager 从官方文档的介绍可以看到ActivityManager的作用&#xff1a; 是与系统所有正在运行着的Acitivity进行交互&#xff0c;对系统所有运行中的Activity相关信息&#xff08;Task&#xff0c;Memory&#xff0c;Service&#xff0c;App&#xff09; 进…

服务器文件每天备份重新命名,定时备份服务器文件至本地电脑

你有么有遇到过以下情况&#xff1a;1 写的脚本忘记保存&#xff0c;然后苦逼地再写一遍2 脚本不小心或者小心地删掉了&#xff0c;但后来又发现很有用&#xff0c;依然苦逼地再写一遍3 实验室的服务器炸了&#xff0c;写的脚本全没了一般情况下&#xff0c;第三种情况不会遇到…