Wpf,如何在可拖动元素内拖动对象?

Wpf, How to drag object inside draggable element?

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

现在我的 拖放 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 class:

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 class,但我不知道如何修复。现在我真的很困惑。

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

我还建议您使用 DevExpress 提供的 attached behavior instead of a class with several attached properties. You can find it in a free MVVM Framework。 通常,在这种情况下,行为会给你更多的自由。