C# wpf中的可排序包装

C# wpf中的可排序包装,c#,wpf,C#,Wpf,我需要实施 转到该链接时,请注意如何拖动对象并将其放置在其他位置。我想知道是否有可能用wpf创建这个。我已经知道如何拖动对象了。有一个漂亮的房间。但我需要将对象对齐。使用最后一个链接将使我能够拖动对象,但我需要在完成拖动后将它们对齐。有很多不同的方法可以做到这一点,但这里有几个想法: 一个自定义面板,带有XOffset、YOffset和IsSnapped的附加属性(默认为true)。当用户拖动项目时,将IsSnapped设置为false,并在拖动时更新XOffset/yoOffset。除非IsS

我需要实施
转到该链接时,请注意如何拖动对象并将其放置在其他位置。我想知道是否有可能用wpf创建这个。我已经知道如何拖动对象了。有一个漂亮的房间。但我需要将对象对齐。使用最后一个链接将使我能够拖动对象,但我需要在完成拖动后将它们对齐。

有很多不同的方法可以做到这一点,但这里有几个想法:

  • 一个自定义面板,带有XOffset、YOffset和IsSnapped的附加属性(默认为true)。当用户拖动项目时,将IsSnapped设置为false,并在拖动时更新XOffset/yoOffset。除非IsSnaped为false,否则面板的布局逻辑可以以强对齐方式排列项目(基于它们的XOffset/YOffset),在这种情况下,它们只显示在(XOffset,YOffset)
  • 使用现有的拖动行为(如blend提供的拖动行为),但在子项被拖放后,将自己的坐标施加到子项上更新:这将不起作用,或者会很混乱,因为Blend会动态修改拖动元素的渲染转换,而不是更新一些附加属性,您可以根据这些属性进行计算
  • 主要是在使用MVVM的视图模型中进行。也就是说,在视图模型上具有顶部、左侧、宽度和高度的属性,所有这些属性都通过行为(DragBehavior和SizeObserver行为)更新。让父视图模型公开子视图模型(每个子视图表示一个可拖动项)。让父VM监视对子坐标的更改,并根据需要进行强制
  • 我现在也在做类似的事情,我选择了#3。现在还没有后悔,这比你在这里试图实现的要复杂得多,所以你不应该有任何拦截器

    更新:以下是我的DragDrop行为:

    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using Kent.Boogaart.HelperTrinity.Extensions;
    
    public static class DragDrop
    {
        public static readonly RoutedEvent PreviewBeginDragEvent = EventManager.RegisterRoutedEvent(
            "PreviewBeginDrag",
            RoutingStrategy.Tunnel,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly RoutedEvent BeginDragEvent = EventManager.RegisterRoutedEvent(
            "BeginDrag",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly RoutedEvent PreviewDragEvent = EventManager.RegisterRoutedEvent(
            "PreviewDrag",
            RoutingStrategy.Tunnel,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly RoutedEvent DragEvent = EventManager.RegisterRoutedEvent(
            "Drag",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly RoutedEvent PreviewEndDragEvent = EventManager.RegisterRoutedEvent(
            "PreviewEndDrag",
            RoutingStrategy.Tunnel,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly RoutedEvent EndDragEvent = EventManager.RegisterRoutedEvent(
            "EndDrag",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(DragDrop));
    
        public static readonly DependencyProperty CanDragProperty = DependencyProperty.RegisterAttached(
            "CanDrag",
            typeof(bool),
            typeof(DragDrop),
            new FrameworkPropertyMetadata(OnCanDragChanged));
    
        public static readonly DependencyProperty IsDragInProgressProperty;
    
        public static readonly DependencyProperty DragParentProperty = DependencyProperty.RegisterAttached(
            "DragParent",
            typeof(FrameworkElement),
            typeof(DragDrop));
    
        public static readonly DependencyProperty XOffsetProperty = DependencyProperty.RegisterAttached(
            "XOffset",
            typeof(double),
            typeof(DragDrop));
    
        public static readonly DependencyProperty YOffsetProperty = DependencyProperty.RegisterAttached(
            "YOffset",
            typeof(double),
            typeof(DragDrop));
    
        private static readonly DependencyPropertyKey isDragInProgressPropertyKey = DependencyProperty.RegisterAttachedReadOnly(
            "IsDragInProgress",
            typeof(bool),
            typeof(DragDrop),
            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
    
        private static readonly DependencyProperty DragPointProperty = DependencyProperty.RegisterAttached(
            "DragPoint",
            typeof(Point?),
            typeof(DragDrop),
            new PropertyMetadata());
    
        static DragDrop()
        {
            IsDragInProgressProperty = isDragInProgressPropertyKey.DependencyProperty;
        }
    
        public static void AddPreviewBeginDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(PreviewBeginDragEvent, handler);
            }
        }
    
        public static void RemovePreviewBeginDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(PreviewBeginDragEvent, handler);
            }
        }
    
        public static void AddBeginDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(BeginDragEvent, handler);
            }
        }
    
        public static void RemoveBeginDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(BeginDragEvent, handler);
            }
        }
    
        public static void AddPreviewDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(PreviewDragEvent, handler);
            }
        }
    
        public static void RemovePreviewDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(PreviewDragEvent, handler);
            }
        }
    
        public static void AddDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(DragEvent, handler);
            }
        }
    
        public static void RemoveDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(DragEvent, handler);
            }
        }
    
        public static void AddPreviewEndDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(PreviewEndDragEvent, handler);
            }
        }
    
        public static void RemovePreviewEndDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(PreviewEndDragEvent, handler);
            }
        }
    
        public static void AddEndDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.AddHandler(EndDragEvent, handler);
            }
        }
    
        public static void RemoveEndDragHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            var inputElement = dependencyObject as IInputElement;
    
            if (inputElement != null)
            {
                inputElement.RemoveHandler(EndDragEvent, handler);
            }
        }
    
        public static bool GetCanDrag(FrameworkElement frameworkElement)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            return (bool)frameworkElement.GetValue(CanDragProperty);
        }
    
        public static void SetCanDrag(FrameworkElement frameworkElement, bool canDrag)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            frameworkElement.SetValue(CanDragProperty, canDrag);
        }
    
        public static FrameworkElement GetDragParent(DependencyObject dependencyObject)
        {
            dependencyObject.AssertNotNull("dependencyObject");
            return dependencyObject.GetValue(DragParentProperty) as FrameworkElement;
        }
    
        public static void SetDragParent(DependencyObject dependencyObject, FrameworkElement dragParent)
        {
            dependencyObject.AssertNotNull("dependencyObject");
            dependencyObject.SetValue(DragParentProperty, dragParent);
        }
    
        public static double GetXOffset(FrameworkElement frameworkElement)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            return (double)frameworkElement.GetValue(XOffsetProperty);
        }
    
        public static void SetXOffset(FrameworkElement frameworkElement, double xOffset)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            frameworkElement.SetValue(XOffsetProperty, xOffset);
        }
    
        public static double GetYOffset(FrameworkElement frameworkElement)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            return (double)frameworkElement.GetValue(YOffsetProperty);
        }
    
        public static void SetYOffset(FrameworkElement frameworkElement, double yOffset)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            frameworkElement.SetValue(YOffsetProperty, yOffset);
        }
    
        public static bool GetIsDragInProgress(DependencyObject dependencyObject)
        {
            dependencyObject.AssertNotNull("dependencyObject");
            return (bool)dependencyObject.GetValue(IsDragInProgressProperty);
        }
    
        private static void SetIsDragInProgress(DependencyObject dependencyObject, bool isDragInProgress)
        {
            dependencyObject.AssertNotNull("dependencyObject");
            dependencyObject.SetValue(isDragInProgressPropertyKey, isDragInProgress);
        }
    
        private static Point? GetDragPoint(FrameworkElement frameworkElement)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            return (Point?)frameworkElement.GetValue(DragPointProperty);
        }
    
        private static void SetDragPoint(FrameworkElement frameworkElement, Point? dragPoint)
        {
            frameworkElement.AssertNotNull("frameworkElement");
            frameworkElement.SetValue(DragPointProperty, dragPoint);
        }
    
        private static void OnCanDragChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var frameworkElement = (FrameworkElement)dependencyObject;
    
            if ((bool)e.NewValue)
            {
                frameworkElement.MouseLeftButtonDown += OnFrameworkElementMouseLeftButtonDown;
                frameworkElement.MouseMove += OnFrameworkElementMouseMove;
                frameworkElement.MouseLeftButtonUp += OnFrameworkElementMouseLeftButtonUp;
    
                var parent = GetDragParent<FrameworkElement>(frameworkElement);
    
                if (parent == null)
                {
                    frameworkElement.SetCurrentValue(XOffsetProperty, 0d);
                    frameworkElement.SetCurrentValue(YOffsetProperty, 0d);
                }
                else
                {
                    var pointRelativeToParent = frameworkElement.TranslatePoint(new Point(0, 0), parent);
                    frameworkElement.SetCurrentValue(XOffsetProperty, pointRelativeToParent.X);
                    frameworkElement.SetCurrentValue(YOffsetProperty, pointRelativeToParent.Y);
                }
            }
            else
            {
                frameworkElement.MouseLeftButtonDown -= OnFrameworkElementMouseLeftButtonDown;
                frameworkElement.MouseMove -= OnFrameworkElementMouseMove;
                frameworkElement.MouseLeftButtonUp -= OnFrameworkElementMouseLeftButtonUp;
            }
        }
    
        private static void OnFrameworkElementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var frameworkElement = (FrameworkElement)sender;
            var parent = GetDragParent<FrameworkElement>(frameworkElement);
    
            if (parent == null)
            {
                return;
            }
    
            var previewBeginDragEventArgs = new RoutedEventArgs(PreviewBeginDragEvent);
            frameworkElement.RaiseEvent(previewBeginDragEventArgs);
    
            if (previewBeginDragEventArgs.Handled)
            {
                return;
            }
    
            SetIsDragInProgress(frameworkElement, true);
            SetDragPoint(frameworkElement, e.GetPosition(parent));
            frameworkElement.CaptureMouse();
            frameworkElement.RaiseEvent(new RoutedEventArgs(BeginDragEvent));
        }
    
        private static void OnFrameworkElementMouseMove(object sender, MouseEventArgs e)
        {
            var frameworkElement = (FrameworkElement)sender;
    
            if (frameworkElement.IsMouseCaptured)
            {
                var previewDragEventArgs = new RoutedEventArgs(PreviewDragEvent);
                frameworkElement.RaiseEvent(previewDragEventArgs);
    
                if (previewDragEventArgs.Handled)
                {
                    return;
                }
    
                var parent = GetDragParent<FrameworkElement>(frameworkElement);
    
                if (parent == null)
                {
                    return;
                }
    
                var currentPointRelativeToParent = e.GetPosition(parent);
                var dragPoint = GetDragPoint(frameworkElement);
                Debug.Assert(dragPoint.HasValue, "dragPoint should be set.");
    
                frameworkElement.SetCurrentValue(XOffsetProperty, GetXOffset(frameworkElement) + (currentPointRelativeToParent.X - dragPoint.Value.X));
                frameworkElement.SetCurrentValue(YOffsetProperty, GetYOffset(frameworkElement) + (currentPointRelativeToParent.Y - dragPoint.Value.Y));
                SetDragPoint(frameworkElement, currentPointRelativeToParent);
                frameworkElement.RaiseEvent(new RoutedEventArgs(DragEvent));
            }
        }
    
        private static void OnFrameworkElementMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var frameworkElement = (FrameworkElement)sender;
    
            if (frameworkElement.IsMouseCaptured)
            {
                frameworkElement.RaiseEvent(new RoutedEventArgs(PreviewEndDragEvent));
                SetDragPoint(frameworkElement, null);
                frameworkElement.ReleaseMouseCapture();
                frameworkElement.RaiseEvent(new RoutedEventArgs(EndDragEvent));
                SetIsDragInProgress(frameworkElement, false);
            }
        }
    
        private static T GetDragParent<T>(DependencyObject dependencyObject)
            where T : DependencyObject
        {
            var dragParent = GetDragParent(dependencyObject) as T;
    
            if (dragParent != null)
            {
                return dragParent;
            }
    
            var parent = VisualTreeHelper.GetParent(dependencyObject);
    
            while (parent != null && !(parent is T))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }
    
            return (T)parent;
        }
    }
    
    使用系统诊断;
    使用System.Windows;
    使用System.Windows.Input;
    使用System.Windows.Media;
    使用Kent.Boogaart.HelperTrinity.Extensions;
    公共静态类DragDrop
    {
    公共静态只读RoutedEvent PreviewRegindrageEvent=EventManager.RegisterRoutedEvent(
    “预览注册表”,
    路由策略,隧道,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读RoutedEvent BeginDragEvent=EventManager.RegisterRoutedEvent(
    “开始”,
    路由策略,泡沫,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读RoutedEvent PreviewDragEvent=EventManager.RegisterRoutedEvent(
    “预览抹布”,
    路由策略,隧道,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读RoutedEvent DrageEvent=EventManager.RegisterRoutedEvent(
    “拖动”,
    路由策略,泡沫,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读RoutedEvent PreviewendDrageEvent=EventManager.RegisterRoutedEvent(
    “预览并拖动”,
    路由策略,隧道,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读RoutedEvent EndDrageEvent=EventManager.RegisterRoutedEvent(
    “结束拖动”,
    路由策略,泡沫,
    类型(RoutedEventHandler),
    类型(DragDrop));
    公共静态只读DependencyProperty CanDragProperty=DependencyProperty.RegisterAttached(
    “烛台”,
    类型(bool),
    类型(DragDrop),
    新的框架属性元数据(OnCanDragChanged));
    公共静态只读从属属性IsDragInProgressProperty;
    公共静态只读DependencyProperty DragParentProperty=DependencyProperty.RegisterAttached(
    “DragParent”,
    类型(框架元件),
    类型(DragDrop));
    公共静态只读DependencyProperty XOffsetProperty=DependencyProperty.RegisterAttached(
    “XOffset”,
    类型(双),
    类型(DragDrop));
    公共静态只读DependencyProperty YOffsetProperty=DependencyProperty.RegisterAttached(
    “YOffset”,
    类型(双),
    类型(DragDrop));
    私有静态只读DependencyPropertyKey isDragInProgressPropertyKey=DependencyProperty.RegisterAttacheReadOnly(
    “IsDragInProgress”,
    类型(bool),
    类型(DragDrop),
    新的FrameworkPropertyMetadata(false,FrameworkPropertyMetadataOptions.Inherits));
    私有静态只读DependencyProperty DragPointProperty=DependencyProperty.RegisterAttached(
    “拖拽点”,
    类型(点?),
    类型(DragDrop),
    新属性元数据());
    静态阻力
    {
    IsDragInProgressProperty=isDragInProgressPropertyKey.DependencyProperty;
    }
    公共静态void AddPreviewBeginDragHandler(DependencyObject DependencyObject,RoutedEventHandler)
    {
    var inputElement=作为IIInputElement的dependencyObject;
    if(inputElement!=null)
    {
    AddHandler(PreviewBegindrageEvent,handler);
    }
    }
    公共静态void removePreviewRegindRagHandler(DependencyObject DependencyObject,RoutedEventHandler)
    {
    var inputElement=作为IIInputElement的dependencyObject;
    if(inputElement!=null)
    {
    RemoveHandler(PreviewRegindrageEvent,handler);
    }
    }
    公共静态void AddBeginDragHandler(DependencyObject DependencyObject,RoutedEventHandler)
    {
    var inputElement=作为IIInputElement的dependencyObject;
    if(inputElement!=null)
    {
    AddHandler(BeginDragEvent,handler);
    }
    }
    公共静态void RemoveBeginDragHandler(DependencyObject DependencyObject,RoutedEventHandler)
    {
    var inputElement=作为IIInputElement的dependencyObject;
    if(inputElement!=null)
    {
    RemoveHandler(BeginDragEvent,handler);
    
    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>  
        <WrapPanel ItemWidth="150">
          <Rectangle Width="50" Height="50" Fill="Red" Margin="10" />
          <Rectangle Width="150" Height="50" Fill="Red" Margin="10" />
          <Rectangle Width="20" Height="50" Fill="Red" Margin="10" />
          <Rectangle Width="50" Height="50" Fill="Red" Margin="10" />
        </WrapPanel>
      </Grid>
    </Page>