|
自定义可移动点二维坐标轴控件
目录
路由参数
X_YResultCollection为当前X轴对应Y轴值存储字典- public class ResultCollectionChangedEventArgs(RoutedEvent routedEvent, object source, IDictionary<double, double> resultCollection) : RoutedEventArgs(routedEvent, source)
- {
- public IDictionary<double, double> X_YResultCollection = resultCollection;
- }
复制代码 坐标轴控件定义
- class CoordinateSystemControl : UserControl
- {
- #region 依赖属性
- /// <summary>
- /// 标注线颜色
- /// </summary>
- public Brush CalloutLineColor
- {
- get { return (Brush)GetValue(CalloutLineColorProperty); }
- set { SetValue(CalloutLineColorProperty, value); }
- }
- /// <summary>
- /// 坐标系颜色
- /// </summary>
- public Brush CoordinateSystemColor
- {
- get { return (Brush)GetValue(CoordinateSystemColorProperty); }
- set { SetValue(CoordinateSystemColorProperty, value); }
- }
- /// <summary>
- /// X轴名称
- /// </summary>
- public string X_AxisName
- {
- get { return (string)GetValue(X_AxisNameProperty); }
- set { SetValue(X_AxisNameProperty, value); }
- }
- /// <summary>
- /// Y轴名称
- /// </summary>
- public string Y_AxisName
- {
- get { return (string)GetValue(Y_AxisNameProperty); }
- set { SetValue(Y_AxisNameProperty, value); }
- }
- /// <summary>
- /// 选择点颜色
- /// </summary>
- public Brush SelectElementColor
- {
- get { return (Brush)GetValue(SelectElementColorProperty); }
- set { SetValue(SelectElementColorProperty, value); }
- }
- /// <summary>
- /// 选择点被选中图标
- /// </summary>
- public Brush SelectedElementColor
- {
- get { return (Brush)GetValue(SelectedElementColorProperty); }
- set { SetValue(SelectedElementColorProperty, value); }
- }
- /// <summary>
- /// Y轴箭头图标
- /// </summary>
- public FrameworkElement YAeeow
- {
- get { return (FrameworkElement)GetValue(YAeeowProperty); }
- set { SetValue(YAeeowProperty, value); }
- }
- /// <summary>
- /// X轴箭头图标
- /// </summary>
- public FrameworkElement XAeeow
- {
- get { return (FrameworkElement)GetValue(XAeeowProperty); }
- set { SetValue(XAeeowProperty, value); }
- }
- /// <summary>
- /// Y轴集合
- /// </summary>
- public IList<double> YCollection
- {
- get { return (IList<double>)GetValue(YCollectionProperty); }
- set { SetValue(YCollectionProperty, value); }
- }
- /// <summary>
- /// X轴集合
- /// </summary>
- public IList<double> XCollection
- {
- get { return (IList<double>)GetValue(XCollectionProperty); }
- set { SetValue(XCollectionProperty, value); }
- }
- /// <summary>
- /// X轴结点对应Y轴值
- /// </summary>
- public IDictionary<double, double> X_YResultCollection
- {
- get { return (IDictionary<double, double>)GetValue(X_YResultCollectionProperty); }
- set { SetValue(X_YResultCollectionProperty, value); }
- }
- /// <summary>
- /// 结果集合改变命令
- /// </summary>
- public ICommand Command
- {
- get { return (ICommand)GetValue(CommandProperty); }
- set { SetValue(CommandProperty, value); }
- }
- #endregion
- #region 路由事件
- /// <summary>
- /// 结果集合改变路由事件
- /// </summary>
- public static readonly RoutedEvent ResultCollectionChangedEvent = EventManager.RegisterRoutedEvent("ResultCollectionChanged", RoutingStrategy.Bubble, typeof(EventHandler<ResultCollectionChangedEventArgs>), typeof(CoordinateSystemControl));
- public event RoutedEventHandler ResultCollectionChanged
- {
- add => AddHandler(ResultCollectionChangedEvent, value);
- remove => RemoveHandler(ResultCollectionChangedEvent, value);
- }
- #endregion
- #region 依赖属性注册
- public static readonly DependencyProperty CalloutLineColorProperty =
- DependencyProperty.Register("CalloutLineColor", typeof(Brush), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata());
- public static readonly DependencyProperty CoordinateSystemColorProperty =
- DependencyProperty.Register("CoordinateSystemColor", typeof(Brush), typeof(CoordinateSystemControl), new PropertyMetadata());
- public static readonly DependencyProperty X_AxisNameProperty =
- DependencyProperty.Register("X_AxisName", typeof(string), typeof(CoordinateSystemControl), new PropertyMetadata("X轴"));
- public static readonly DependencyProperty Y_AxisNameProperty =
- DependencyProperty.Register("Y_AxisName", typeof(string), typeof(CoordinateSystemControl), new PropertyMetadata("Y轴"));
- public static readonly DependencyProperty SelectElementColorProperty =
- DependencyProperty.Register("SelectElementColor", typeof(Brush), typeof(CoordinateSystemControl), new PropertyMetadata());
- public static readonly DependencyProperty SelectedElementColorProperty =
- DependencyProperty.Register("SelectedElementColor", typeof(Brush), typeof(CoordinateSystemControl), new PropertyMetadata());
- public static readonly DependencyProperty YAeeowProperty =
- DependencyProperty.Register("YAeeow", typeof(FrameworkElement), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata());
- public static readonly DependencyProperty XAeeowProperty =
- DependencyProperty.Register("XAeeow", typeof(FrameworkElement), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata());
- public static readonly DependencyProperty YCollectionProperty =
- DependencyProperty.Register("YCollection", typeof(IList<double>), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, YCollectionCallback));
- public static readonly DependencyProperty XCollectionProperty =
- DependencyProperty.Register("XCollection", typeof(IList<double>), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, XCollectionCallback));
- public static readonly DependencyProperty X_YResultCollectionProperty =
- DependencyProperty.Register("X_YResultCollection", typeof(IDictionary<double, double>), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, X_YResultCollectionChangedCallback));
- public static readonly DependencyProperty CommandProperty =
- DependencyProperty.Register("Command", typeof(ICommand), typeof(CoordinateSystemControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, CommandChangedCallback));
- #endregion
- #region 私有字段
- private bool _isFirstLoaded = false;
- //坐标系顶点留空距离
- private readonly int _spacedPoints = 15;
- private readonly Canvas _canvas;
- //X、Y轴线
- private Line _yLine;
- private Line _xLine;
- private Point _originPoint;
- private Point _yEndpoint;
- private Point _xEndpoint;
- private int _ySingleDistance;
- private int _xSingleDistance;
- private double _proportionSize;
- //选择点实时数据位置变形
- private Transform _transform_textBox;
- //选择点位置校准变形
- private Transform _transform_chekEllipse;
- //拖动选择点位置变形
- private Transform _transform_clickMoveEllipse;
- //选择点显示值TextBox映射
- private readonly Dictionary<Ellipse, TextBox> _selectEllipse_TextBoxMap = [];
- //选择点与连接线链表
- private readonly LinkedList<Shape> _selectEllipse_ConnectionLines = [];
- private readonly Dictionary<double, Ellipse> _xValue_EllipseMap = [];
- #endregion
- public CoordinateSystemControl()
- {
- _canvas = new Canvas() { Margin = new Thickness(20) };
- _canvas.SizeChanged += Canvas_SizeChanged;
- _canvas.Loaded += Canvas_Loaded;
- this.AddChild(_canvas);
- _transform_textBox = new TranslateTransform() { X = -13, Y = -25 };
- _transform_chekEllipse = new TranslateTransform() { X = -7, Y = -5 };
- _transform_clickMoveEllipse = new TransformGroup
- {
- Children = { new TranslateTransform() { X = -3, Y = -5 }, new ScaleTransform(1.5, 1.5) }
- };
- //初始化依赖属性
- CalloutLineColor = Brushes.DarkBlue;
- CoordinateSystemColor = Brushes.Black;
- SelectElementColor = Brushes.BlueViolet;
- SelectedElementColor = Brushes.MediumVioletRed;
- }
- #region 事件与回调
- private void Canvas_Loaded(object sender, RoutedEventArgs e)
- {
- Initialize();
- _isFirstLoaded = true;
- }
- private static void CommandChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue is ICommand command)
- {
- var sender = d as CoordinateSystemControl;
- command.CanExecuteChanged -= sender!.Command_CanExecuteChanged;
- command.CanExecuteChanged += sender.Command_CanExecuteChanged;
- }
- }
- private void Command_CanExecuteChanged(object? sender, EventArgs e)
- {
- IsEnabled = Command.CanExecute(null);
- }
- private static void YCollectionCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.OldValue is ObservableCollection<double> oldValue)
- {
- oldValue.CollectionChanged -= YCollectionChangedCallback;
- }
- if (e.NewValue is ObservableCollection<double> newValue)
- {
- newValue.CollectionChanged += YCollectionChangedCallback;
- }
- void YCollectionChangedCallback(object? sender, NotifyCollectionChangedEventArgs e)
- {
- if (d is CoordinateSystemControl control)
- {
- if (control._isFirstLoaded)
- {
- control.Initialize();
- }
- }
- }
- }
- private static void XCollectionCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.OldValue is ObservableCollection<double> oldValue)
- {
- oldValue.CollectionChanged -= XCollectionChangedCallback;
- }
- if (e.NewValue is ObservableCollection<double> newValue)
- {
- newValue.CollectionChanged += XCollectionChangedCallback;
- }
- void XCollectionChangedCallback(object? sender, NotifyCollectionChangedEventArgs e)
- {
- if (d is CoordinateSystemControl control)
- {
- if (control._isFirstLoaded)
- {
- control.Initialize();
- }
- }
- }
- }
- private static void X_YResultCollectionChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs de)
- {
- if (de.OldValue is ObservableDictionary<double, double> oldValue)
- {
- oldValue.CollectionChanged -= X_YResultCollectionChangedCallback;
- }
- if (de.NewValue is ObservableDictionary<double, double> newValue)
- {
- newValue.CollectionChanged += X_YResultCollectionChangedCallback;
- }
- void X_YResultCollectionChangedCallback(object? sender, NotifyCollectionChangedEventArgs e)
- {
- if (d is not CoordinateSystemControl control) return;
- if (control.IsMouseCaptureWithin) return;
- var oldValue = de.OldValue as ObservableDictionary<double, double>;
- if (de.NewValue is not ObservableDictionary<double, double> newValue) return;
- foreach (var item in newValue)
- {
- double x = item.Key;
- var point = oldValue?.Where(n => n.Key == x).FirstOrDefault();
- if (point is null || point.Value.Value != item.Value)
- {
- if (!control._xValue_EllipseMap.TryGetValue(x, out var ellipse)) continue;
- double YUnit = control.CalculateYUnit(item.Value);
- control.SetSelectEllipsePosition(ellipse, control.GetActualCanvasTop(YUnit));
- }
- }
- }
- }
- private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
- {
- var textBox = (TextBox)sender;
- if (!textBox.IsKeyboardFocused) return;
- if (!double.TryParse(textBox.Text, out double value) || !ValidateNumber(value))
- {
- textBox.Background = Brushes.OrangeRed;
- return;
- }
- textBox.Background = Brushes.Transparent;
- double result = CalculateYUnit(value);
- var selectEllipse = _selectEllipse_TextBoxMap.Single(n => n.Value.GetHashCode() == textBox.GetHashCode()).Key;
- var canvasTop = GetActualCanvasTop(result);
- SetSelectEllipsePosition(selectEllipse, canvasTop);
- StoragePosition(selectEllipse);
- bool ValidateNumber(double value)
- {
- return value >= 0 && value <= YCollection.Last();
- }
- }
- private void SelectEllipse_Control_MouseUp(object sender, MouseButtonEventArgs e)
- {
- if (e.LeftButton == MouseButtonState.Released)
- {
- Mouse.Capture(null);
- var element = (Ellipse)sender;
- element.RenderTransform = _transform_chekEllipse;
- element.Fill = SelectElementColor;
- StoragePosition(element);
- RaiseEventInvokeCommand();
- }
- e.Handled = true;
- }
- private void SelectEllipse_Control_MouseMove(object sender, MouseEventArgs e)
- {
- if (e.LeftButton == MouseButtonState.Pressed && Mouse.Captured == sender)
- {
- var ellipse = (Ellipse)sender;
- var position = ValidataMouseYValue(e.GetPosition(_canvas).Y - 5);
- SetSelectEllipsePosition(ellipse, position);
- }
- e.Handled = true;
- }
- private void SelectEllipse_MouseDown(object sender, MouseButtonEventArgs e)
- {
- if (e.LeftButton == MouseButtonState.Pressed)
- {
- Mouse.Capture((IInputElement)sender);
- var element = (Ellipse)sender;
- element.RenderTransform = _transform_clickMoveEllipse;
- element.Fill = SelectedElementColor;
- }
- e.Handled = true;
- }
- #endregion
- void Initialize()
- {
- YCollection ??= [1, 2, 3, 4, 5, 6, 7, 8, 9];
- XCollection ??= [1, 2, 3, 4, 5, 6, 7, 8, 9];
- //清理缓存数据
- _selectEllipse_TextBoxMap.Clear();
- _selectEllipse_ConnectionLines.Clear();
- _xValue_EllipseMap.Clear();
- if (_canvas.Children.Count > 0) _canvas.Children.RemoveRange(0, _canvas.Children.Count);
- _originPoint = new Point(0, _canvas.ActualHeight);
- _yEndpoint = new Point(_originPoint.X, _spacedPoints + 7);
- _xEndpoint = new Point(_canvas.ActualWidth - _spacedPoints - X_AxisName.Length * 7, _originPoint.Y);
- _ySingleDistance = (int)CalculateSingleDistance(Math.Abs(_originPoint.Y - _yEndpoint.Y), YCollection);
- _xSingleDistance = (int)CalculateSingleDistance(Math.Abs(_originPoint.X - _xEndpoint.X), XCollection);
- _proportionSize = _ySingleDistance / 7;
- _yLine = new Line() { Stroke = CoordinateSystemColor, StrokeThickness = 2, X1 = _yEndpoint.X, Y1 = _yEndpoint.Y, X2 = _originPoint.X, Y2 = _originPoint.Y };
- _xLine = new Line() { Stroke = CoordinateSystemColor, StrokeThickness = 2, X1 = _originPoint.X, Y1 = _originPoint.Y, X2 = _xEndpoint.X, Y2 = _xEndpoint.Y };
- _canvas.Children.Add(_yLine);
- _canvas.Children.Add(_xLine);
- var y_AxisText = new TextBlock { Text = Y_AxisName };
- var x_AxisText = new TextBlock { Text = X_AxisName };
- _canvas.Children.Add(y_AxisText);
- _canvas.Children.Add(x_AxisText);
- Canvas.SetTop(x_AxisText, _yEndpoint.Y - _spacedPoints);
- Canvas.SetLeft(x_AxisText, _yEndpoint.X + _spacedPoints);
- Canvas.SetTop(y_AxisText, _xEndpoint.Y - _spacedPoints * 2);
- Canvas.SetLeft(y_AxisText, _xEndpoint.X);
- //加入坐标轴图标
- AddAeeow();
- //添加标注线和标注值和选择点
- AddCalloutLine();
- }
- private void AddAeeow()
- {
- YAeeow ??= new Path()
- {
- Data = new PathGeometry()
- {
- Figures = [new PathFigure(){
- IsClosed = true,
- StartPoint = new Point(0, 0),
- Segments = [new LineSegment(new Point(-_proportionSize, _proportionSize/2), true),
- new LineSegment(new Point(0, -_proportionSize), true),
- new LineSegment(new Point(_proportionSize, _proportionSize/2), true)]
- }]
- },
- Fill = CoordinateSystemColor
- };
- XAeeow ??= new Path()
- {
- Data = new PathGeometry()
- {
- Figures = [new PathFigure() {
- IsClosed = true,
- StartPoint = new Point(0, 0),
- Segments = [new LineSegment(new Point(-_proportionSize/2, _proportionSize), true),
- new LineSegment(new Point(_proportionSize, 0), true),
- new LineSegment(new Point(-_proportionSize/2, -_proportionSize), true)]
- }]
- },
- Fill = CoordinateSystemColor
- };
- _canvas.Children.Add(YAeeow);
- _canvas.Children.Add(XAeeow);
- Canvas.SetTop(this.YAeeow, _yEndpoint.Y);
- Canvas.SetLeft(this.YAeeow, _yEndpoint.X);
- Canvas.SetTop(this.XAeeow, _xEndpoint.Y);
- Canvas.SetLeft(this.XAeeow, _xEndpoint.X);
- }
- private void AddCalloutLine()
- {
- //添加Y轴标注线和标注值
- AddYCalloutLines();
- //添加X轴标注线和标注值和选择点
- AddXCalloutLinesAndSelectEllipses();
- }
- private void AddYCalloutLines()
- {
- for (int i = 1; i < YCollection.Count + 1; i++)
- {
- var canvasTop = GetActualCanvasTop(i);
- //添加标注线和标注值
- var line = new Line() { Stroke = CalloutLineColor, StrokeThickness = 1, X1 = 0, Y1 = 0, X2 = _proportionSize, Y2 = 0 };
- var text = new TextBlock() { Text = YCollection[i - 1].ToString(), RenderTransformOrigin = new(0.5, 0.5), RenderTransform = new TranslateTransform() { X = -12, Y = -8 } };
- Canvas.SetLeft(line, _originPoint.X);
- Canvas.SetTop(line, canvasTop);
- Canvas.SetLeft(text, _originPoint.X);
- Canvas.SetTop(text, canvasTop);
- _canvas.Children.Add(line);
- _canvas.Children.Add(text);
- }
- }
- private void AddXCalloutLinesAndSelectEllipses()
- {
- for (int i = 1; i < XCollection.Count + 1; i++)
- {
- var currentValue = XCollection[i - 1];
- var cancasLeft = GetActualCanvasLeft(i);
- var line = new Line() { Stroke = CalloutLineColor, StrokeThickness = 1, X1 = 0, Y1 = 0, X2 = 0, Y2 = -_proportionSize };
- var textBlock = new TextBlock() { Text = currentValue.ToString(), RenderTransformOrigin = new(0.5, 0.5), RenderTransform = new TranslateTransform() { X = -5, Y = 5 } };
- Canvas.SetLeft(line, cancasLeft);
- Canvas.SetTop(line, _originPoint.Y);
- Canvas.SetLeft(textBlock, cancasLeft);
- Canvas.SetTop(textBlock, _originPoint.Y);
- _canvas.Children.Add(textBlock);
- _canvas.Children.Add(line);
- //添加选择点
- var selectEllipse = new Ellipse
- {
- Width = 14,
- Height = 14,
- Fill = SelectElementColor,
- RenderTransformOrigin = new Point(0.5, 0.5),
- RenderTransform = _transform_chekEllipse,
- };
- selectEllipse.AddHandler(MouseDownEvent, new MouseButtonEventHandler(SelectEllipse_MouseDown));
- selectEllipse.AddHandler(MouseMoveEvent, new MouseEventHandler(SelectEllipse_Control_MouseMove));
- selectEllipse.AddHandler(MouseUpEvent, new MouseButtonEventHandler(SelectEllipse_Control_MouseUp));
- X_YResultCollection ??= new ObservableDictionary<double, double>();
- bool excist = X_YResultCollection.Any(n => n.Key == currentValue);
- string text = excist ? X_YResultCollection!.Single(n => n.Key == currentValue).Value.ToString("F2") : string.Empty;
- var textBox = new TextBox() { Text = text, Background = Brushes.Transparent, BorderThickness = new(0), RenderTransform = _transform_textBox };
- textBox.TextChanged += TextBox_TextChanged;
- _canvas.Children.Add(selectEllipse);
- _canvas.Children.Add(textBox);
- _selectEllipse_TextBoxMap.Add(selectEllipse, textBox);
- _xValue_EllipseMap.Add(currentValue, selectEllipse);
- AddSelectEllipse(selectEllipse, i, currentValue);
- AddConnectionLine(selectEllipse, i == XCollection.Count);
- }
- }
- private void AddConnectionLine(Ellipse selectEllipse, bool isLast = false)
- {
- if (_selectEllipse_ConnectionLines.Count == 0)
- {
- _selectEllipse_ConnectionLines.AddFirst(selectEllipse);
- }
- else
- {
- var lastConnectionLine = (Line)_selectEllipse_ConnectionLines.Last!.Value;
- lastConnectionLine.X2 = Canvas.GetLeft(selectEllipse);
- lastConnectionLine.Y2 = Canvas.GetTop(selectEllipse);
- _selectEllipse_ConnectionLines.AddLast(selectEllipse);
- }
- if (isLast) return;
- var ConnectionLine = new Line() { StrokeThickness = 1, X1 = Canvas.GetLeft(selectEllipse), Y1 = Canvas.GetTop(selectEllipse), X2 = 0, Y2 = 0, Stroke = Brushes.LightGray };
- _selectEllipse_ConnectionLines.AddLast(ConnectionLine);
- _canvas.Children.Add(ConnectionLine);
- //将选择点置于最上层
- Panel.SetZIndex(selectEllipse, 1);
- }
- private void ChangeConnectionPosition(Ellipse ellipse, double canvasTop)
- {
- var linkedNode = _selectEllipse_ConnectionLines.Find(ellipse);
- if (linkedNode?.Previous != null)
- {
- var previousLine = (Line)linkedNode.Previous.ValueRef;
- previousLine.Y2 = canvasTop;
- }
- if (linkedNode?.Next != null)
- {
- var nextLine = (Line)linkedNode.Next.ValueRef;
- nextLine.Y1 = canvasTop;
- }
- }
- private double ValidataMouseYValue(double yPosition)
- {
- double MaxYValue = _originPoint.Y - _ySingleDistance * YCollection.Count;
- if (yPosition < MaxYValue)
- {
- yPosition = MaxYValue;
- }
- if (yPosition > _originPoint.Y)
- {
- yPosition = _originPoint.Y;
- }
- return yPosition;
- }
- private void StoragePosition(Ellipse ellipse)
- {
- var xUnit = Math.Abs(_originPoint.X - Canvas.GetLeft(ellipse)) / _xSingleDistance;
- var xValue = XCollection[(int)xUnit - 1];
- var yUnit = (_originPoint.Y - Canvas.GetTop(ellipse)) / _ySingleDistance;
- double yValue = CalculateYValue(yUnit);
- X_YResultCollection[xValue] = Math.Round(yValue, 2);
- }
- private double CalculateYValue(double yunit)
- {
- var yArray = YCollection.ToArray();
- bool minFlag = yunit >= 1;
- if (yunit >= yArray.Length) return yArray.Last();
- int lastValueIndex = (int)yunit - 1;
- double lastValue = minFlag ? yArray[lastValueIndex] : 0;
- double nextValue = yArray[lastValueIndex + 1];
- return lastValue + (yunit - lastValueIndex - 1) * (nextValue - lastValue);
- }
- private double CalculateYUnit(double yValue)
- {
- double lastValue = 0;
- int i = -1;
- foreach (var item in YCollection)
- {
- i++;
- if (item < yValue)
- {
- lastValue = item;
- continue;
- }
- return i + (yValue - lastValue) / (item - lastValue);
- }
- return 0;
- }
- private void AddSelectEllipse(Ellipse ellipse, double xUnit, double xValue)
- {
- if (X_YResultCollection.Where(n => n.Key == xValue).Any())
- {
- var yValue = X_YResultCollection.Single(n => n.Key == xValue).Value;
- double yUnit = CalculateYUnit(yValue);
- SetSelectEllipsePosition(ellipse, GetActualCanvasTop(yUnit), GetActualCanvasLeft(xUnit));
- }
- else
- {
- X_YResultCollection.Add(xValue, 1);
- AddSelectEllipse(ellipse, xUnit, xValue);
- }
- }
- private void SetSelectEllipsePosition(Ellipse ellipse, double top, double? left = null)
- {
- Canvas.SetTop(ellipse, top);
- var textBox = _selectEllipse_TextBoxMap[ellipse];
- Canvas.SetTop(textBox, top);
- //改变对应textblock值
- var yUnit = (_originPoint.Y - top) / _ySingleDistance;
- double yValue = CalculateYValue(yUnit);
- textBox.Text = yValue.ToString("F2");
- //改变连接线位置
- ChangeConnectionPosition(ellipse, top);
- if (left.HasValue)
- {
- Canvas.SetLeft(ellipse, (double)left);
- Canvas.SetLeft(textBox, (double)left);
- }
- }
- private double CalculateSingleDistance(double totalDistance, IEnumerable<double> values)
- {
- return (totalDistance - _spacedPoints) / values.Count();
- }
- private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- if (e.PreviousSize.Width != 0 && e.PreviousSize.Height != 0)
- {
- Initialize();
- }
- e.Handled = true;
- }
- private double GetActualCanvasLeft(double unit) => _originPoint.X + _xSingleDistance * unit;
- private double GetActualCanvasTop(double unit) => _originPoint.Y - _ySingleDistance * unit;
- private void RaiseEventInvokeCommand()
- {
- ResultCollectionChangedEventArgs args = new(ResultCollectionChangedEvent, this, X_YResultCollection);
- RaiseEvent(args);
- if (Command?.CanExecute(null) ?? true)
- {
- Command?.Execute(X_YResultCollection);
- }
- }
- public static double CalculateYValue(Dictionary<double, double> dic, double xValue)
- {
- double lastX = 0;
- double lastY = 0;
- foreach (var point in dic)
- {
- if (xValue > point.Key)
- {
- lastX = point.Key;
- lastY = point.Value;
- continue;
- }
- else if (xValue == point.Key)
- {
- return point.Value;
- }
- return (point.Value - lastY) / (point.Key - lastX) * (xValue - lastX) / (point.Key - lastX) + lastY;
- }
- return dic[dic.Max(n => n.Key)];
- }
- }
复制代码 Demo
在拖动完选择点后会触发命令和抛出路由事件
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="400" />
- <RowDefinition Height="*" />
- </Grid.RowDefinitions>
- <local:CoordinateSystemControl
- Command="{Binding TestCommand}"
- X_AxisName="X"
- XCollection="{Binding XCollection}"
- YCollection="{Binding YCollection}"
- X_YResultCollection="{Binding Datas}"
- Y_AxisName="Y" />
- <Button
- Grid.Row="1"
- Width="40"
- Height="20"
- Command="{Binding ClickCommand}"
- Content="click me" />
- </Grid>
复制代码- public ObservableCollection<double> XCollection { get; set; } = [1, 3, 5, 7, 9];
- public ObservableCollection<double> YCollection { get; set; } = [1, 3, 5, 7, 9];
- public ObservableDictionary<double, double> Datas { get; set; } = [];
- //构造函数
- public ViewModel()
- {
- Datas.Add(1, 1);
- Datas.Add(3, 1);
- Datas.Add(5, 1);
- Datas.Add(7, 1);
- Datas.Add(9, 1);
- }
- [RelayCommand]
- public async Task Test(IDictionary<double, double> data)
- {
- }
- [RelayCommand]
- private void Click()
- {
- Datas[1.0] = 5;
- }
复制代码 注意
ObservableDictionary可查看[https://www.cnblogs.com/yinyuessh/p/18205333]
希望能给你带来帮助 --来自.net菜鸡粉丝的祝愿
来源:https://www.cnblogs.com/yinyuessh/p/18205346
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|