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,一经查实,立即删除!

相关文章

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

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

记录一次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;无处不用数学回首往昔数学始终伴随我们左右纵横交错的几何、繁琐复杂的运算难以求解的方程…

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&#…

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

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

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

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

Android之ActivityManager与Proxy模式的运用

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

化学到底有多难难难难!为了让学生搞懂化学,竟然...

▲ 点击查看提到化学&#xff0c;大家脑子里都会想到什么呢&#xff1f;枯燥的化学式&#xff1f;还是难背的元素周期表&#xff1f;还是让人头疼的化学考试题&#xff1f;在由NHK&#xff0c;NHK Educational Corp、西南德国广播&#xff08;SWR&#xff09;、卡塔尔半岛电视台…

面试题--特别是字节对齐

来源&#xff1a;http://www.cnblogs.com/Braveliu/archive/2013/01/04/2844757.html 【1】设置或者清除某位。 示例代码如下: 1 #include<iostream>2 using namespace std;3 4 #define BIT3 (0x1<<3)5 6 void Set_bit3(int &a)7 {8 a|BIT3;9 } 10 11…

配置基于python的VIM环境

配置基于python的VIM环境 安装插件管理工具 为防止过多插件管理的麻烦&#xff0c;首先安装vim的插件管理工具Vundle。vundle本身的github软件已经有相关的中文文档&#xff0c;地址如下&#xff1a; vundle官方中文文档 复制其配置&#xff0c; set nocompatible …

Npgsql 6.0.2 发布,赶紧升级!!!

❝PostgreSQL 是一种特性非常齐全的自由软件的对象-关系型数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;是以加州大学计算机系开发的 POSTGRES&#xff0c;4.2版本为基础的对象关系型数据库管理系统。POSTGRES 的许多领先概念只是在比较迟的时候才出现在商业网站数…

Android之中获取应用程序(包)的信息-----PackageManager的使用(一)

转载&#xff1a;http://blog.csdn.net/qinjuning/article/details/6867806 本节内容是如何获取Android系统中应用程序的信息&#xff0c;主要包括packagename、label、icon、占用大小等。具体分为两个 部分&#xff0c;计划如下&#xff1a; 第一部分&#xff1a; 获取应用程…

dnf公共频道服务器不稳定已从初始化状态,DNF公共频道跨区列表 组队连不上必看...

DNF公共频道组队连接不上&#xff1f;在大转移版本之后很多玩家表示DNF公共频道不能组队&#xff0c;实际上这个和大家所在的DNF公共频道跨区有关&#xff0c;位于同一个跨区的玩家之间才能够组队&#xff0c;这里是一份DNF公共频道跨区列表&#xff0c;除此之外还有公共频道的…

了解开源文化

开放源码软件运动是计算机科学领域的一种文化现象&#xff0c;源自***对智慧成果共享、自由的追求。开源运动发展到现在&#xff0c;这种能够积极促进人类文明发展的文化已经***到信息、教育、健康等领域&#xff0c;融入了哲学范畴。开放源码运动的史前史包括了整个Unix&#…

jquery验证手机号码和邮箱地址例子

为什么80%的码农都做不了架构师&#xff1f;>>> //jquery验证邮箱 function checkSubmitEmail(){ if($("#email").val()""){ $("#confirmMsg").html("邮箱地址不能为空&#xff01;"); $("#email").focus()…

令人难忘的初吻描写......

1 我可以把你删了吗&#xff0c;我没有内存了&#xff08;via.豆瓣陈皮&#xff0c;侵删&#xff09;▼2 黑社会平时都在干些什么&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 老师头秃是有原因的▼4 是谁炸了珍珠港&#xff1f;&#xff08;素材来源网络&…

Android之获取应用程序(包)的大小-----PackageManager的使用(二)

http://blog.csdn.net/qinjuning/article/details/6892054 通过第一部分 << Android中获取应用程序(包)的信息-----PackageManager的使用(一) >>的介绍&#xff0c;对PackageManager以及 AndroidManife.xml定义的节点信息类XXXInfo类都有了一定的认识。 本部分的内…