Wpf,如何在draggable元素中拖动对象?

时间:2017-06-08 20:08:13

标签: wpf xaml mvvm drag-and-drop behavior

我正在开发WPF应用程序。我应该在其他可拖动对象中实现具有可拖动对象的设计器页面。看图:enter image description here

现在我的拖放1和2 正常工作,但当我尝试拖动内部对象1 并执行拖放3 时它工作不正常。我没有拖动内部对象1 ,而是拖动主对象1

我的xaml代码:

<ItemsControl ItemsSource="{Binding MasterObjects}">
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Canvas/>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
    <Style TargetType="ContentPresenter">
        <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
        <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
        <Setter Property="Width" Value="{Binding Path=Width}" />
        <Setter Property="Height" Value="{Binding Path=Height}" />
    </Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Grid behaviors:DragBehavior.Drag="True">
            <Rectangle Fill="LightGray" Stroke="SlateGray" StrokeThickness="1" />
            <TextBlock Text="{Binding Name}" />
            <ItemsControl ItemsSource="{Binding InnerObjects}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
                        <Setter Property="Width" Value="{Binding Path=Width}" />
                        <Setter Property="Height" Value="{Binding Path=Height}" />
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid behaviors:DragBehavior.Drag="True">
                            <Rectangle Fill="LightGray" Stroke="SlateGray" StrokeThickness="1" />
                            <TextBlock Text="{Binding Name}" />
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

我的DragBehavior类:

public class DragBehavior
{
    public readonly TranslateTransform Transform = new TranslateTransform();
    private Point _elementStartPosition2;
    private Point _mouseStartPosition2;
    private static DragBehavior _instance = new DragBehavior();
    public static DragBehavior Instance
    {
        get { return _instance; }
        set { _instance = value; }
    }

    public static bool GetDrag(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsDragProperty);
    }

    public static void SetDrag(DependencyObject obj, bool value)
    {
        obj.SetValue(IsDragProperty, value);
    }

    public static readonly DependencyProperty IsDragProperty =
      DependencyProperty.RegisterAttached(
          "Drag",
          typeof(bool), 
          typeof(DragBehavior),
          new PropertyMetadata(false, OnDragChanged));

    private static void OnDragChanged(object sender, DependencyPropertyChangedEventArgs e)
    {

        // ignoring error checking
        var element = (UIElement)sender;
        var isDrag = (bool)(e.NewValue);

        Instance = new DragBehavior();
        ((UIElement)sender).RenderTransform = Instance.Transform;

        if (isDrag)
        {
            element.MouseLeftButtonDown += Instance.ElementOnMouseLeftButtonDown;
            element.MouseLeftButtonUp += Instance.ElementOnMouseLeftButtonUp;
            element.MouseMove += Instance.ElementOnMouseMove;
        }
        else
        {
            element.MouseLeftButtonDown -= Instance.ElementOnMouseLeftButtonDown;
            element.MouseLeftButtonUp -= Instance.ElementOnMouseLeftButtonUp;
            element.MouseMove -= Instance.ElementOnMouseMove;
        }
    }

    private void ElementOnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        var parent = Application.Current.MainWindow;
        _mouseStartPosition2 = mouseButtonEventArgs.GetPosition(parent);
        ((UIElement)sender).CaptureMouse();
    }

    private void ElementOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        ((UIElement)sender).ReleaseMouseCapture();
        _elementStartPosition2.X = Transform.X;
        _elementStartPosition2.Y = Transform.Y;
    }

    private void ElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
    {
        var parent = Application.Current.MainWindow;
        var mousePos = mouseEventArgs.GetPosition(parent);
        var diff = (mousePos - _mouseStartPosition2);
        if (!((UIElement)sender).IsMouseCaptured) return;
        Transform.X = _elementStartPosition2.X + diff.X;
        Transform.Y = _elementStartPosition2.Y + diff.Y;
    }
}

我想我应该修复DragBehaviour类,但我不知道怎么做。现在我真的很困惑。

1 个答案:

答案 0 :(得分:1)

从内部容器到父容器的 MouseLeftButtonDown 事件是bubbling。尝试在事件处理程序中将 e.Handled 属性设置为true。在这种情况下,只会引发第一个单击元素的处理程序,并且您的代码应该正常工作。

我还建议您使用attached behavior而不是具有多个附加属性的类。您可以在DevExpress提供的免费MVVM Framework中找到它。 通常,行为会在这种情况下为您提供更多自由。