X3

RedSky

导航

WPF Canvas子控件拖拽行为,以及ListBox+Canvas场景

1

    public class DragMoveBehavior : Behavior<UIElement>
    {
        Window window;
        Canvas parent;
        bool isDown;
        Point prePosition = new Point();
        public Type TargetType { get; set; }
        UIElement Target { get; set; }

        protected override void OnAttached()
        {
            base.OnAttached();


            Target = TargetType == null ? AssociatedObject : (UIElement)base.AssociatedObject.FirstParentOrNull(TargetType);
            Target.PreviewMouseLeftButtonDown += MouseLeftButtonDown;
            Target.PreviewMouseLeftButtonUp += MouseLeftButtonUp;
            window = Window.GetWindow(Target);
            window.LostFocus += Window_LostFocus;

            parent = LogicalTreeHelper.GetParent(Target) as Canvas;
            if (parent == null)
                parent = Target.FirstParentOrNull<Canvas>();
            parent.PreviewMouseLeftButtonUp += MouseLeftButtonUp;
            parent.PreviewMouseMove += MouseMove;
        }

        private void Window_LostFocus(object sender, RoutedEventArgs e)
        {
            isDown = false;
            parent.ReleaseMouseCapture();
        }

        private void MouseMove(object sender, MouseEventArgs e)
        {
            if (!isDown) return;
            Point currentPosition = GetPosition(e);

            double offsetx = currentPosition.X - prePosition.X;
            double offsety = currentPosition.Y - prePosition.Y;
            double left = Canvas.GetLeft(Target);
            double top = Canvas.GetTop(Target);
            double l = double.IsNaN(left) ? 0 : left + offsetx;
            double t = double.IsNaN(top) ? 0 : top + offsety;
            Canvas.SetLeft(Target, l);
            Canvas.SetTop(Target, t);
            prePosition = currentPosition;
        }

        private void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            parent.ReleaseMouseCapture();
            isDown = false;
        }

        private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (isDown) return;
            isDown = true;
            prePosition = GetPosition(e);
            parent.CaptureMouse();
        }

        Point GetPosition(MouseEventArgs e)
        {
            return e.GetPosition(parent);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            Target.PreviewMouseLeftButtonDown -= MouseLeftButtonDown;
            Target.PreviewMouseLeftButtonUp -= MouseLeftButtonUp;
            window.LostFocus -= Window_LostFocus;

            parent.PreviewMouseLeftButtonUp -= MouseLeftButtonUp;
            parent.PreviewMouseMove -= MouseMove;
        }
    }

 

2、调用方式:

.net framework方式

引用System.Windows.Interactivity类库;

在xaml中添加

xmlns:action="http://schemas.microsoft.com/expression/2010/interactivity"

.net5 .net6方式

nuget引用Microsoft.Xaml.Behaviors.Wpf包

在xaml中添加

xmlns:action="http://schemas.microsoft.com/xaml/behaviors"

 

然后在想要移动的控件里添加如下代码,比如是想拖动button:

案例一:

<Button Width="100" Height="50" Content="拖动我">
       <action:Interaction.Behaviors>
              <local:DragMoveBehavior />
       </action:Interaction.Behaviors>
</Button>

 案例二:

<ListBox SelectionMode="Extended" x:Name="listCanvas">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Canvas.Left" Value="{Binding Left}"/>
            <Setter Property="Canvas.Top" Value="{Binding Top}"/>
            <Setter Property="Width" Value="{Binding Width}"/>
            <Setter Property="Height" Value="{Binding Height}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Button Background="{Binding Brush}">
                            <action:Interaction.Behaviors>
                                <local:DragMoveBehavior TargetType="{x:Type ListBoxItem}"/>
                            </action:Interaction.Behaviors>
                        </Button>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
    public class CanvaObj
    {
        public double Left { get; set; }
        public double Top { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
        public Brush Brush { get; set; }
    }

    List<CanvaObj> list = new List<CanvaObj>
    {
        new CanvaObj { Left = 50, Top = 20, Width = 40, Height = 40, Brush = Brushes.AliceBlue },
        new CanvaObj { Left = 150, Top = 20, Width = 60, Height = 20, Brush = Brushes.Aquamarine },
        new CanvaObj { Left = 50, Top = 120, Width = 30, Height = 60, Brush = Brushes.Fuchsia }
    };
    listCanvas.ItemsSource = list;

 

posted on 2020-01-14 17:48  HotSky  阅读(1029)  评论(2编辑  收藏  举报