2013-11-26 3 views
0

내 문제는 내가 2 개의 노드가 선으로 연결되어 있다는 것입니다. 한 노드를 캔버스의 아무 위치로 드래그하면 원래 위치로 되돌아 가야합니다. 또한 원래 위치로 되돌아 오는 동안 애니메이션 기능을 수행해야합니다 (진동 기능 또는 바운스/탄성 완화 효과). 여기서 문제는 노드를 애니메이트하는 동안 노드가 노드를 연결하는 선을 따라 붙지 않는 것입니다. 또한 노드가 xaml에 없습니다. 그들은 동적으로 생성 된 코드 숨김 상태에 있습니다. 따라서 LayoutUpdated 이벤트도 사용할 수 없습니다.Dragcompleted에서 개체에 연결된 선을 애니메이트하는 방법은 무엇입니까?

 private void OnDragDelta(object sender, DragDeltaEventArgs e) 
    { 
     var thumb = e.Source as MyThumb; 

     var left = Canvas.GetLeft(thumb) + e.HorizontalChange; 
     var top = Canvas.GetTop(thumb) + e.VerticalChange; 

     Canvas.SetLeft(thumb, left); 
     Canvas.SetTop(thumb, top); 

     double x1 = Canvas.GetLeft(thumb) - e.HorizontalChange; //previous 
     double y1 = Canvas.GetTop(thumb) - e.VerticalChange; //previous 
     double x2 = Canvas.GetLeft(thumb); //current 
     double y2 = Canvas.GetTop(thumb); //current 
     this.Lable1.Content = "Old x=" + x1 + "|old y=" + y1 + "|new x=" + x2 + "|new y=" + y2; 

    } 

     private void OnDragCompleted(object sender, DragCompletedEventArgs e) 
    { 
     var thumb = e.Source as MyThumb; 

     double x1 = Canvas.GetLeft(thumb) - e.HorizontalChange; 
     double y1 = Canvas.GetTop(thumb) - e.VerticalChange; 

     double x2 = Canvas.GetLeft(thumb); 
     double y2 = Canvas.GetTop(thumb); 
     AnimateThis4(x1, x2, y1, y2, thumb); 
    } 

     private void AnimateThis4(double x1, double x2, double y1, double y2, MyThumb thumb) 
    { 
     // Create a duration of 2 seconds. 
     Duration duration = new Duration(TimeSpan.FromSeconds(2)); 

     // Create two DoubleAnimations and set their properties. 
     DoubleAnimation myDoubleAnimation1 = new DoubleAnimation(); 
     DoubleAnimation myDoubleAnimation2 = new DoubleAnimation(); 

     myDoubleAnimation1.Duration = duration; 
     myDoubleAnimation2.Duration = duration; 

     myDoubleAnimation1.FillBehavior = FillBehavior.Stop; 
     myDoubleAnimation2.FillBehavior = FillBehavior.Stop; 

     ElasticEase ea = new ElasticEase(); 
     ea.EasingMode = EasingMode.EaseOut; 
     ea.Springiness = 2; 
     ea.Oscillations = 5; 

     myDoubleAnimation1.EasingFunction = ea; 
     myDoubleAnimation2.EasingFunction = ea; 

     Storyboard sb = new Storyboard(); 
     sb.Duration = duration; 

     sb.Children.Add(myDoubleAnimation1); 
     sb.Children.Add(myDoubleAnimation2); 

     Storyboard.SetTarget(myDoubleAnimation1, thumb); 
     Storyboard.SetTarget(myDoubleAnimation2, thumb); 

     Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(Canvas.Left)")); 
     Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath("(Canvas.Top)")); 



     //Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath(TranslateTransform.XProperty)); 
     //Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath(TranslateTransform.YProperty)); 

     myDoubleAnimation1.From = x2; 
     myDoubleAnimation2.From = y2; 

     myDoubleAnimation1.To = x1; 
     myDoubleAnimation2.To = y1; 

     myDoubleAnimation1.Completed += new EventHandler((sender, e) => da_Completed(sender, e, x1, y1, thumb)); 
     myDoubleAnimation2.Completed += new EventHandler((sender, e) => da_Completed(sender, e, x1, y1, thumb)); 

     // Begin the animation. 
     sb.Begin(); 


     this.Lable1.Content = "Old x=" + x1 + "|old y=" + y1 + "|new x=" + x2 + "|new y=" + y2; 
    } 

    // AFTER ANIMATION IS OVER, SET THE THUMB POSITION TO ORIGINAL 
    void da_Completed(object sender, EventArgs e, double X, double Y, MyThumb thumb) 
    { 
     Canvas.SetLeft(thumb, X); 
     Canvas.SetTop(thumb, Y); 

    } 

    // LINE IS CREATED HERE. I CANT SEEM TO BIND THE THUMB TO THE LINE 
    private void btnJoinLineClick(object sender, RoutedEventArgs e) 
    { 


     line = new Line(); 
     myCanvas.Children.Add(line); 
     line.Stroke = Brushes.Red; 
     line.StrokeThickness = 2; 
     line.X1 = Canvas.GetLeft(myThumb2) + myThumb2.ActualWidth/2; 
     line.Y1 = Canvas.GetTop(myThumb2) + myThumb2.ActualHeight/2; 
     line.X2 = Canvas.GetLeft(myThumb1) + myThumb1.ActualWidth/2; 
     line.Y2 = Canvas.GetTop(myThumb1) + myThumb1.ActualHeight/2; 


     //DependencyProperty dpX1 = Line.X1Property; 
     //Binding b1 = new Binding(); 
     //b1.Path = new PropertyPath("Canvas.Left"); 
     //b1.ElementName = this.myThumb2.Name; 
     ////b.Source = itemsControl.ItemContainerGenerator.ContainerFromIndex(0); 
     //BindingOperations.SetBinding(line, dpX1, b1); 


     //DependencyProperty dpY1 = Line.Y1Property; 
     //Binding b2 = new Binding(); 
     //b2.Path = new PropertyPath("Canvas.Top"); 
     //b2.ElementName = this.myThumb2.Name; 
     ////b.Source = itemsControl.ItemContainerGenerator.ContainerFromIndex(0); 
     //BindingOperations.SetBinding(line, dpY1, b2); 


     DependencyProperty dpX2 = Line.X2Property; 
     Binding b3 = new Binding(); 
     b3.Path = new PropertyPath("Canvas.Left"); 
     //b3.ElementName = this.myThumb1.Name; 
     b3.Source = Canvas.GetLeft(myThumb1) + myThumb1.ActualWidth/2; 
     //b.Source = itemsControl.ItemContainerGenerator.ContainerFromIndex(0); 
     BindingOperations.SetBinding(line, dpX2, b3); 


     DependencyProperty dpY2 = Line.Y2Property; 
     Binding b4 = new Binding(); 
     b4.Path = new PropertyPath("Canvas.Top"); 
     b4.ElementName = this.myThumb1.Name; 

     //b4.Source = Canvas.GetTop(myThumb1) + myThumb1.ActualHeight/2; 
     BindingOperations.SetBinding(line, dpY2, b4); 


    } 

답변

0
에게

코드가 조금 추한있을 수 있습니다 ...하지만 작동이 당신을 도울 것입니다 바랍니다 어떤 문제가 바로 떠나 : 여기

내 코드입니다 : 뒤에 코드에서 XAML

<my:MyThumb x:Name="myThumb1" LayoutUpdated="myThumb1_LayoutUpdated" DragCompleted="OnDragCompleted" DragDelta="OnDragDelta" Canvas.Left="250" Canvas.Top="70" Template="{StaticResource template1}"> 
     </my:MyThumb> 
     <my:MyThumb x:Name="myThumb2" DragCompleted="OnDragCompleted" DragDelta="OnDragDelta" Canvas.Left="50" Canvas.Top="70" Template="{StaticResource template1}"/> 

의견.

주의해야 할 두 가지 사항이 있습니다. 1, WPF는 연결된 DP를 요소에 바인딩하려고 할 때 propertyPath 문자열을 지원하지 않으므로 "Canvas.Top"대신 새 PropertyPath (Canvas.TopProperty)를 사용할 수 있지만 시나리오에서는 엄지의 가운데 위치가 필요합니다. 그래서 당신은이 속성을 직접 바인딩 할 수 없습니다. 2, 사용자 지정 DP를 사용하므로 애니메이션 시작 (AddValueChanged 문)시이 속성을 업데이트해야합니다.

namespace WpfApplicationThumbDrag 
{ 
    public class MyThumb : Thumb 
    { 
     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 

      this.DragDelta += thumb_DragDelta; 
      this.DragCompleted += new DragCompletedEventHandler(MyThumb_DragCompleted); 

      this.Loaded += (s, e) => { UpdateCenter(); }; 

      var left = DependencyPropertyDescriptor.FromProperty(Canvas.LeftProperty, typeof(Canvas)); 
      var right = DependencyPropertyDescriptor.FromProperty(Canvas.RightProperty, typeof(Canvas)); 

      left.AddValueChanged(this, OnCanvasLeftRightChanged); 
      right.AddValueChanged(this, OnCanvasLeftRightChanged); 
     } 

     private void OnCanvasLeftRightChanged(object sender, EventArgs e) 
     { 
      UpdateCenter(); 
     } 

     private void MyThumb_DragCompleted(object sender, DragCompletedEventArgs e) 
     { 
      var thumb = e.Source as MyThumb; 

      double x1 = Canvas.GetLeft(thumb) - e.HorizontalChange; 
      double y1 = Canvas.GetTop(thumb) - e.VerticalChange; 

      double x2 = Canvas.GetLeft(thumb); 
      double y2 = Canvas.GetTop(thumb); 
      AnimateThis4(x1, x2, y1, y2, thumb); 
     } 

     private void AnimateThis4(double x1, double x2, double y1, double y2, MyThumb thumb) 
     { 
      // Create a duration of 2 seconds. 
      Duration duration = new Duration(TimeSpan.FromSeconds(2)); 

      // Create two DoubleAnimations and set their properties. 
      DoubleAnimation myDoubleAnimation1 = new DoubleAnimation(); 
      DoubleAnimation myDoubleAnimation2 = new DoubleAnimation(); 

      myDoubleAnimation1.Duration = duration; 
      myDoubleAnimation2.Duration = duration; 

      myDoubleAnimation1.FillBehavior = FillBehavior.Stop; 
      myDoubleAnimation2.FillBehavior = FillBehavior.Stop; 

      ElasticEase ea = new ElasticEase(); 
      ea.EasingMode = EasingMode.EaseOut; 
      ea.Springiness = 2; 
      ea.Oscillations = 5; 

      myDoubleAnimation1.EasingFunction = ea; 
      myDoubleAnimation2.EasingFunction = ea; 

      Storyboard sb = new Storyboard(); 
      sb.Duration = duration; 

      sb.Children.Add(myDoubleAnimation1); 
      sb.Children.Add(myDoubleAnimation2); 

      Storyboard.SetTarget(myDoubleAnimation1, thumb); 
      Storyboard.SetTarget(myDoubleAnimation2, thumb); 

      Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(Canvas.Left)")); 
      Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath("(Canvas.Top)")); 


      //Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath(TranslateTransform.XProperty)); 
      //Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath(TranslateTransform.YProperty)); 

      myDoubleAnimation1.From = x2; 
      myDoubleAnimation2.From = y2; 

      myDoubleAnimation1.To = x1; 
      myDoubleAnimation2.To = y1; 

      myDoubleAnimation1.Completed += new EventHandler((sender, e) => da_Completed(sender, e, x1, y1, thumb)); 
      myDoubleAnimation2.Completed += new EventHandler((sender, e) => da_Completed(sender, e, x1, y1, thumb)); 

      // Begin the animation. 
      sb.Begin(); 
     } 

     // AFTER ANIMATION IS OVER, SET THE THUMB POSITION TO ORIGINAL 
     void da_Completed(object sender, EventArgs e, double X, double Y, MyThumb thumb) 
     { 
      Canvas.SetLeft(thumb, X); 
      Canvas.SetTop(thumb, Y); 

     } 

     public Point Center 
     { 
      get { return (Point)GetValue(CenterProperty); } 
      set { SetValue(CenterProperty, value); } 
     } 

     public static readonly DependencyProperty CenterProperty = 
      DependencyProperty.Register("Center", typeof(Point), typeof(MyThumb), new UIPropertyMetadata(new Point())); 


     private void thumb_DragDelta(object sender, DragDeltaEventArgs e) 
     { 
      var left = Canvas.GetLeft(this) + e.HorizontalChange; 
      var top = Canvas.GetTop(this) + e.VerticalChange; 

      Canvas.SetLeft(this, left); 
      Canvas.SetTop(this, top); 

     } 

     private void UpdateCenter() 
     { 
      var p = new Point(); 
      p.X = Canvas.GetLeft(this) + this.ActualWidth/2; 
      p.Y = Canvas.GetTop(this) + this.ActualHeight/2; 

      this.Center = p; 
     } 
    } 

    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void btnJoinLine_Click(object sender, RoutedEventArgs e) 
     { 
      var line = new Line(); 
      myCanvas.Children.Add(line); 
      line.Stroke = Brushes.Red; 
      line.StrokeThickness = 2; 
      line.X1 = Canvas.GetLeft(myThumb2) + myThumb2.ActualWidth/2; 
      line.Y1 = Canvas.GetTop(myThumb2) + myThumb2.ActualHeight/2; 
      line.X2 = Canvas.GetLeft(myThumb1) + myThumb1.ActualWidth/2; 
      line.Y2 = Canvas.GetTop(myThumb1) + myThumb1.ActualHeight/2; 


      //Binding Line start X 
      var binding1 = new Binding(); 
      binding1.ElementName = "myThumb1"; 
      binding1.Path = new PropertyPath("Center.X"); 
      BindingOperations.SetBinding(line, Line.X1Property, binding1); 

      //Binding Line start Y 
      var binding11 = new Binding(); 
      binding11.ElementName = "myThumb1"; 
      binding11.Path = new PropertyPath("Center.Y"); 
      BindingOperations.SetBinding(line, Line.Y1Property, binding11); 

      //Binding Line end X 
      var binding2 = new Binding(); 
      binding2.ElementName = "myThumb2"; 
      binding2.Path = new PropertyPath("Center.X"); 
      BindingOperations.SetBinding(line, Line.X2Property, binding2); 

      //Binding Line end Y 
      var binding22 = new Binding(); 
      binding22.ElementName = "myThumb2"; 
      binding22.Path = new PropertyPath("Center.Y"); 
      BindingOperations.SetBinding(line, Line.Y2Property, binding22); 
     } 
    } 
} 


<Window x:Class="WpfApplicationThumbDrag.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplicationThumbDrag" 
     Title="MainWindow" 
     Width="525" 
     Height="350"> 
    <Canvas x:Name="myCanvas"> 
     <local:MyThumb x:Name="myThumb1" 
       Canvas.Left="250" 
       Canvas.Top="70" 
       Width="100" 
       Height="30" /> 
     <local:MyThumb x:Name="myThumb2" 
       Canvas.Left="50" 
       Canvas.Top="70" 
       Width="100" 
       Height="30" /> 

     <Button x:Name="btnJoinLine" 
       HorizontalAlignment="Right" 
       VerticalAlignment="Top" 
       Click="btnJoinLine_Click" 
       Content="join" /> 
    </Canvas> 
</Window> 
+0

감사합니다. 바인딩 코드가 작동했습니다. 나는 그것을 잘못하고 있었을지도 모른다. Dependancy 속성이 도움이되었습니다. –

관련 문제