<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      yinyuessh

      導(dǎo)航

      自定義可移動(dòng)點(diǎn)二維坐標(biāo)軸控件

      自定義可移動(dòng)點(diǎn)二維坐標(biāo)軸控件

      目錄

      路由參數(shù)

      X_YResultCollection為當(dāng)前X軸對(duì)應(yīng)Y軸值存儲(chǔ)字典

      public class ResultCollectionChangedEventArgs(RoutedEvent routedEvent, object source, IDictionary<double, double> resultCollection) : RoutedEventArgs(routedEvent, source)
      {
          public IDictionary<double, double> X_YResultCollection = resultCollection;
      }
      

      坐標(biāo)軸控件定義

      class CoordinateSystemControl : UserControl
      {
          #region 依賴屬性
      
          /// <summary>
          /// 標(biāo)注線顏色
          /// </summary>
          public Brush CalloutLineColor
          {
              get { return (Brush)GetValue(CalloutLineColorProperty); }
              set { SetValue(CalloutLineColorProperty, value); }
          }
      
          /// <summary>
          /// 坐標(biāo)系顏色
          /// </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>
          /// 選擇點(diǎn)顏色
          /// </summary>
          public Brush SelectElementColor
          {
              get { return (Brush)GetValue(SelectElementColorProperty); }
              set { SetValue(SelectElementColorProperty, value); }
          }
      
          /// <summary>
          /// 選擇點(diǎn)被選中圖標(biāo)
          /// </summary>
          public Brush SelectedElementColor
          {
              get { return (Brush)GetValue(SelectedElementColorProperty); }
              set { SetValue(SelectedElementColorProperty, value); }
          }
      
          /// <summary>
          /// Y軸箭頭圖標(biāo)
          /// </summary>
          public FrameworkElement YAeeow
          {
              get { return (FrameworkElement)GetValue(YAeeowProperty); }
              set { SetValue(YAeeowProperty, value); }
          }
      
          /// <summary>
          /// X軸箭頭圖標(biāo)
          /// </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軸結(jié)點(diǎn)對(duì)應(yīng)Y軸值
          /// </summary>
          public IDictionary<double, double> X_YResultCollection
          {
              get { return (IDictionary<double, double>)GetValue(X_YResultCollectionProperty); }
              set { SetValue(X_YResultCollectionProperty, value); }
          }
      
          /// <summary>
          /// 結(jié)果集合改變命令
          /// </summary>
          public ICommand Command
          {
              get { return (ICommand)GetValue(CommandProperty); }
              set { SetValue(CommandProperty, value); }
          }
      
          #endregion
      
          #region 路由事件
      
          /// <summary>
          /// 結(jié)果集合改變路由事件
          /// </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 依賴屬性注冊(cè)
      
          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;
          //坐標(biāo)系頂點(diǎn)留空距離
          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;
      
          //選擇點(diǎn)實(shí)時(shí)數(shù)據(jù)位置變形
          private Transform _transform_textBox;
          //選擇點(diǎn)位置校準(zhǔn)變形
          private Transform _transform_chekEllipse;
          //拖動(dòng)選擇點(diǎn)位置變形
          private Transform _transform_clickMoveEllipse;
          private QuadraticEase _easingFunction;
      
          //選擇點(diǎn)顯示值TextBox映射
          private readonly Dictionary<Ellipse, TextBox> _selectEllipse_TextBoxMap = [];
          //選擇點(diǎn)與連接線鏈表
          private readonly LinkedList<Shape> _selectEllipse_ConnectionLines = [];
          private readonly Dictionary<double, Ellipse> _xValue_EllipseMap = [];
      
      
          #endregion
      
          public CoordinateSystemControl()
          {
              _canvas = new Canvas() { Margin = new Thickness(30) };
              _canvas.SizeChanged += Canvas_SizeChanged;
              _canvas.Loaded += Canvas_Loaded;
              this.AddChild(_canvas);
      
              _transform_textBox = new TranslateTransform() { X = -18, Y = -35 };
              _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) }
              };
              _easingFunction = new()
              {
                  EasingMode = EasingMode.EaseOut// 設(shè)置緩動(dòng)模式為EaseOut,即先快后慢
              };
      
              //初始化依賴屬性
              CalloutLineColor = Brushes.DarkBlue;
              CoordinateSystemColor = Brushes.Black;
              SelectElementColor = Brushes.BlueViolet;
              SelectedElementColor = Brushes.MediumVioletRed;
          }
      
          #region 事件與回調(diào)
          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];
              //清理緩存數(shù)據(jù)
              _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 = CalculateSingleDistance(Math.Abs(_originPoint.Y - _yEndpoint.Y), YCollection);
              _xSingleDistance = CalculateSingleDistance(Math.Abs(_originPoint.X - _xEndpoint.X), XCollection);
              _proportionSize = 8;
      
              _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 };
      
              //給線條添加動(dòng)畫(huà)
              _yLine.BeginAnimation(Line.Y1Property, new DoubleAnimation(_originPoint.Y, _yEndpoint.Y, TimeSpan.FromSeconds(1)));
              _xLine.BeginAnimation(Line.X2Property, new DoubleAnimation(_originPoint.X, _xEndpoint.X, TimeSpan.FromSeconds(1)));
      
              _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(y_AxisText, _yEndpoint.Y - _spacedPoints);
              Canvas.SetLeft(y_AxisText, _yEndpoint.X + _spacedPoints);
              Canvas.SetTop(x_AxisText, _xEndpoint.Y - _spacedPoints * 2);
              Canvas.SetLeft(x_AxisText, _xEndpoint.X);
      
              y_AxisText.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(_originPoint.Y, _yEndpoint.Y - _spacedPoints, TimeSpan.FromSeconds(1))
              {
                  EasingFunction = _easingFunction 
              });
              x_AxisText.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(_originPoint.X, _xEndpoint.X + _spacedPoints, TimeSpan.FromSeconds(1))
              {
                  EasingFunction = _easingFunction
              });
      
              //加入坐標(biāo)軸圖標(biāo)
              AddAeeow();
              //添加標(biāo)注線和標(biāo)注值和選擇點(diǎn)
              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);
      
              XAeeow.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(_originPoint.X, _xEndpoint.X, TimeSpan.FromSeconds(1)));
              YAeeow.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(_originPoint.Y, _yEndpoint.Y, TimeSpan.FromSeconds(1)));
          }
      
          private void AddCalloutLine()
          {
              //添加Y軸標(biāo)注線和標(biāo)注值
              AddYCalloutLines();
              //添加X(jué)軸標(biāo)注線和標(biāo)注值和選擇點(diǎn)
              AddXCalloutLinesAndSelectEllipses();
          }
      
          private void AddYCalloutLines()
          {
              for (int i = 1; i < YCollection.Count + 1; i++)
              {
                  var canvasTop = GetActualCanvasTop(i);
                  //添加標(biāo)注線和標(biāo)注值
                  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 = -16, Y = -13 } };
      
                  // 添加動(dòng)畫(huà)
                  var time = TimeSpan.FromSeconds(i * 0.15);
                  SetAnimation(text, time);
                  SetAnimation(line, time);
      
                  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);
      
                  //添加選擇點(diǎn)
                  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;
      
                  //添加動(dòng)畫(huà)
                  TimeSpan time = TimeSpan.FromSeconds(i * 0.15);
                  SetAnimation(selectEllipse, time);
                  SetAnimation(textBox, time);
                  SetAnimation(line, time);
                  SetAnimation(textBlock, time);
      
                  _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);
              //將選擇點(diǎn)置于最上層
              Panel.SetZIndex(selectEllipse, 1);
          }
      
          private void SetAnimation(UIElement uIElement, TimeSpan durationTime)
          {
              uIElement.Opacity = 0;
              var fadeInAnimation = new DoubleAnimation()
              {
                  From = 0,
                  To = 1,
                  Duration = durationTime,
              };
              uIElement.BeginAnimation(OpacityProperty, fadeInAnimation);
          }
      
          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);
      
              //改變對(duì)應(yīng)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 int CalculateSingleDistance(double totalDistance, IEnumerable<double> values)
          {
              var result = (totalDistance - _spacedPoints) / values.Count();
              return result < 1 ? 1 : (int)result;
          }
      
          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

      在拖動(dòng)完選擇點(diǎn)后會(huì)觸發(fā)命令和拋出路由事件

      • View
      <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>
      
      • ViewModel
        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; } = [];
      
      //構(gòu)造函數(shù)
        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可查看[http://www.rzrgm.cn/yinyuessh/p/18205333]

      希望能給你帶來(lái)幫助 --來(lái)自.net菜雞粉絲的祝愿

      posted on 2024-05-22 08:34  音樂(lè)隨生活  閱讀(138)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 女厕偷窥一区二区三区| 精品国产午夜福利在线观看| 久久久亚洲欧洲日产国码αv| 欧美激情精品久久久久久| 国产精品成人国产乱| 日韩精品中文字幕第二页| 高清有码国产一区二区| 暖暖视频日本在线观看| 国产午夜福利一区二区三区| 91福利一区福利二区| 淮安市| 青青草久热这里只有精品| 江源县| 东京热人妻无码一区二区av| 国产精品无码久久久久AV| 国产小嫩模无套中出视频| 蜜臀久久99精品久久久久久| 欧美猛少妇色xxxxx猛叫| 色综合天天综合天天更新| 亚洲中文精品一区二区| 午夜国产小视频| 中文字幕波多野不卡一区| 国产又爽又黄又刺激的视频| 国产午夜三级一区二区三| 亚洲国产精品综合久久网各| 午夜免费福利小电影| 成人3D动漫一区二区三区| 绯色蜜臀av一区二区不卡| 潘金莲高清dvd碟片| 久久久久无码中| 新营市| 欧美和黑人xxxx猛交视频| 亚洲欧美综合精品成| 中文字幕人成无码免费视频| 成在线人永久免费视频播放| 波多野结衣美乳人妻hd电影欧美| 虎白女粉嫩尤物福利视频| 亚洲欧洲∨国产一区二区三区| 久久国产免费观看精品| 人妻少妇久久中文字幕| 中文字幕有码高清日韩|