2008-11-16 22 views
16

Próbuję utworzyć aplikację WPF, w której można przeciągnąć obraz.Przeciąganie obrazu w WPF

Obecnie mam obraz umieszczony na środku okna, i myślę o użyciu trzech mouseevents MouseDown, MouseMove i MouseUp, aby obliczyć nową pozycję podczas przeciągania obrazu.

Czy są jakieś inne dobre pomysły, jak to zrobić? Jestem całkowicie nowy w WPF, więc mój sposób myślenia wciąż jest w świecie Windows Forms.

O ile widzę, potrzebuję użyć , aby uzyskać absolutne pozycjonowanie.

Odpowiedz

31

ok, tutaj jest załączony właściwość „zachowanie”, które można użyć, aby każdy element przeciągany pod warunkiem, że znajduje się na płótnie:

public class DraggableExtender : DependencyObject 
{ 
    // This is the dependency property we're exposing - we'll 
    // access this as DraggableExtender.CanDrag="true"/"false" 
    public static readonly DependencyProperty CanDragProperty = 
     DependencyProperty.RegisterAttached("CanDrag", 
     typeof(bool), 
     typeof(DraggableExtender), 
     new UIPropertyMetadata(false, OnChangeCanDragProperty)); 

    // The expected static setter 
    public static void SetCanDrag(UIElement element, bool o) 
    { 
     element.SetValue(CanDragProperty, o); 
    } 

    // the expected static getter 
    public static bool GetCanDrag(UIElement element) 
    { 
     return (bool) element.GetValue(CanDragProperty); 
    } 

    // This is triggered when the CanDrag property is set. We'll 
    // simply check the element is a UI element and that it is 
    // within a canvas. If it is, we'll hook into the mouse events 
    private static void OnChangeCanDragProperty(DependencyObject d, 
       DependencyPropertyChangedEventArgs e) 
    { 
     UIElement element = d as UIElement; 
     if (element == null) return; 

     if (e.NewValue != e.OldValue) 
     { 
      if ((bool)e.NewValue) 
      { 
       element.PreviewMouseDown += element_PreviewMouseDown; 
       element.PreviewMouseUp += element_PreviewMouseUp; 
       element.PreviewMouseMove += element_PreviewMouseMove; 
      } 
      else 
      { 
       element.PreviewMouseDown -= element_PreviewMouseDown; 
       element.PreviewMouseUp -= element_PreviewMouseUp; 
       element.PreviewMouseMove -= element_PreviewMouseMove; 
      } 
     } 
    } 

    // Determine if we're presently dragging 
    private static bool _isDragging = false; 
    // The offset from the top, left of the item being dragged 
    // and the original mouse down 
    private static Point _offset; 

    // This is triggered when the mouse button is pressed 
    // on the element being hooked 
    static void element_PreviewMouseDown(object sender, 
      System.Windows.Input.MouseButtonEventArgs e) 
    { 
     // Ensure it's a framework element as we'll need to 
     // get access to the visual tree 
     FrameworkElement element = sender as FrameworkElement; 
     if (element == null) return; 

     // start dragging and get the offset of the mouse 
     // relative to the element 
     _isDragging = true; 
     _offset = e.GetPosition(element); 
    } 

    // This is triggered when the mouse is moved over the element 
    private static void element_PreviewMouseMove(object sender, 
       MouseEventArgs e) 
    { 
     // If we're not dragging, don't bother - also validate the element 
     if (!_isDragging) return; 

     FrameworkElement element = sender as FrameworkElement; 
     if (element == null) return; 

     Canvas canvas = element.Parent as Canvas; 
     if(canvas == null) return; 

     // Get the position of the mouse relative to the canvas 
     Point mousePoint = e.GetPosition(canvas); 

     // Offset the mouse position by the original offset position 
     mousePoint.Offset(-_offset.X, -_offset.Y); 

     // Move the element on the canvas 
     element.SetValue(Canvas.LeftProperty, mousePoint.X); 
     element.SetValue(Canvas.TopProperty, mousePoint.Y); 
    } 

    // this is triggered when the mouse is released 
    private static void element_PreviewMouseUp(object sender, 
      MouseButtonEventArgs e) 
    { 
     _isDragging = false; 
    } 

} 

Następnie można użyć tego w XAML importując nazw klasa jest zawarte w (coś takiego :)

<Window x:Class="WPFFunWithDragging.Window1" 
     xmlns:local="clr-namespace:WPFFunWithDragging" .. > 

a następnie można po prostu ustawić DraggableExtender.CanDrag = "true" na elementach przeciągnąć wokół:

<Canvas> 
    <Image Source="Garden.jpg" 
      Width="50" 
      Canvas.Left="10" Canvas.Top="10" 
      local:DraggableExtender.CanDrag="true"/> 
</Canvas> 

Mam nadzieję, że jest to przydatne :)

+2

Dzięki - bardzo użyteczny kod. Poprawiłbym to nieco, gdy element schwytałby mysz w dół myszy i zwolnił przechwycenie myszy myszką w górę. W przeciwnym razie łatwo przegapić ruchy myszą, jeśli z jakiegoś powodu mysz wykracza poza granice przeciąganego przedmiotu. –

+0

Dobra rada - właśnie zrobiłem coś podobnego w przypadku bezramowych okien, dodam tę sugestię;) –

+0

Czy istnieje sposób na wymuszenie przeciągania obrazu tylko w granicy obszaru roboczego? – Melursus