RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 591337
Accepted
trydex
trydex
Asked:2020-11-15 23:19:25 +0000 UTC2020-11-15 23:19:25 +0000 UTC 2020-11-15 23:19:25 +0000 UTC

拖放预览

  • 772

如何在 MVVM 的框架中制作这样一个带有预览的拖放,就像在 gif 上一样?

是Canvas与对象绑定的集合。按照此答案中的示例,每个对象都已CustomControl在其中实现了通常的拖放操作。

我想在MouseMove制作VisualBrush当前对象时,用这个画笔绘制一个新的矩形并拖动它。但毕竟,它Canvas是绑定到集合中的,事实证明,这个矩形也需要添加到集合中才能显示出来。

<ItemsControl ItemsSource="{Binding itemsList}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" Width="1000" Height="1000"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
           <local:CustomControl/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Canvas.Left" Value="{Binding Position.X}"/>
            <Setter Property="Canvas.Top" Value="{Binding Position.Y}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

在此处输入图像描述

wpf
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    VladD
    2020-01-23T01:38:44Z2020-01-23T01:38:44Z

    让我们尝试调整此答案中的代码,以便在您放手之前它不会在现实中包裹正方形。

    idea cVisualBrush是个好主意,这样我们就可以很容易地“乘以”已有的元素。但是在集合中加入一个dummy元素并不好,毕竟我们的动作关注的是UI层面,而不是模型。

    因此,VM 级别完全不会发生任何变化,这很好。

    让我们在方块列表的顶部添加另一个级别。为了不干扰,我们将使其对鼠标透明。我们需要绑定两个元素的大小,为此我们需要一个名称和Binding:

    <Window x:Class="MvvmDraggable2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MvvmDraggable2"
            Title="Draggable squares 2" Height="350" Width="525">
        <Grid>
            <ItemsControl ItemsSource="{Binding Squares}" Width="300" Height="300"
                          Background="Beige" Name="DraggableItemsHost">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <local:DraggableSquare
                            DraggedImageContainer="{Binding ElementName=DraggedImageContainer}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Canvas.Left" Value="{Binding Position.X}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Position.Y}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
            <Canvas IsHitTestVisible="False">
                <Rectangle Opacity="0.4" Name="DraggedImageContainer" Visibility="Collapsed"/>
            </Canvas>
        </Grid>
    </Window>
    

    为它添加了一个名称ItemsControl,DraggableSquare为它出现了一个额外的绑定(稍后会详细介绍),并且在底部出现Canvas了包含所需元素的内容。

    接下来,DraggbleSquare。我们正在稍微改变我们的内部逻辑。UpdatePosition现在只会在释放鼠标或窗口失去焦点时调用。

    void OnDragMove(object sender, MouseEventArgs e)
    {
        //UpdatePosition(e);
        UpdateDraggedSquarePosition(e);
    }
    
    void FinishDrag(object sender, MouseEventArgs e)
    {
        MouseMove -= OnDragMove;
        LostMouseCapture -= OnLostCapture;
        UpdatePosition(e);
        UpdateDraggedSquarePosition(null);
    }
    

    逻辑的新部分:UpdateDraggedSquarePosition. 为此,我们需要一个新的依赖属性DraggedImageContainer,其中我们已经在 XAML 中放置了一个表示移动图像的元素。

    (把它放得更高,靠近RequestMoveCommand。)

    #region dp Shape DraggedImageContainer
    public Shape DraggedImageContainer
    {
        get { return (Shape)GetValue(DraggedImageContainerProperty); }
        set { SetValue(DraggedImageContainerProperty, value); }
    }
    
    public static readonly DependencyProperty DraggedImageContainerProperty =
        DependencyProperty.Register(
            "DraggedImageContainer", typeof(Shape), typeof(DraggableSquare));
    #endregion
    

    实际上是新逻辑本身:

    void UpdateDraggedSquarePosition(MouseEventArgs e)
    {
        var dragImageContainer = DraggedImageContainer;
        if (dragImageContainer == null)
            return;
        var needVisible = e != null;
        var wasVisible = dragImageContainer.Visibility == Visibility.Visible;
        // включаем/выключаем видимость перемещаемой картинки
        dragImageContainer.Visibility = needVisible ? Visibility.Visible : Visibility.Collapsed;
        if (!needVisible) // если мы выключились, нам больше нечего делать
            return;
        if (!wasVisible) // а если мы были выключены и включились,
        {                // нам надо привязать изображение себя
            dragImageContainer.Fill = new VisualBrush(this);
            dragImageContainer.SetBinding( // а также ширину/высоту
                Shape.WidthProperty,
                new Binding(nameof(ActualWidth)) { Source = this });
            dragImageContainer.SetBinding(
                Shape.HeightProperty,
                new Binding(nameof(ActualHeight)) { Source = this });
            // Binding нужен потому, что наш размер может по идее измениться
        }
        // перемещаем картинку на нужную позицию
        var parent = FindParent<Canvas>(dragImageContainer);
        var position = e.GetPosition(parent) - relativeMousePos;
        Canvas.SetLeft(dragImageContainer, position.X);
        Canvas.SetTop(dragImageContainer, position.Y);
    }
    

    是的,我不得不稍微改变一下GetParent以使其适用于任意元素:

    static private T FindParent<T>(FrameworkElement from) where T : FrameworkElement
    {
        FrameworkElement current = from;
        T t;
        do
        {
            t = current as T;
            current = (FrameworkElement)VisualTreeHelper.GetParent(current);
        }
        while (t == null && current != null);
        return t;
    }
    

    并以OnMouseDown书面形式

    container = FindParent<Canvas>(this);
    

    就这样了。

    为了拍出漂亮的照片,我还给 加了颜色SquareVM:

    Color color;
    public Color Color
    {
        get { return color; }
        set { if (color != value) { color = value; NotifyPropertyChanged(); } }
    }
    

    并将颜色设置为MainVM:

    class MainVM : VM
    {
        public ObservableCollection<SquareVM> Squares { get; } =
            new ObservableCollection<SquareVM>()
            {
                new SquareVM() { Position = new Point(30, 30),
                                 Color = Color.FromRgb(0x3D, 0x31, 0x5B) },
                new SquareVM() { Position = new Point(100, 70),
                                 Color = Color.FromRgb(0x44, 0x4B, 0x6E) },
                new SquareVM() { Position = new Point(80, 0),
                                 Color = Color.FromRgb(0x70, 0x8B, 0x75) },
                new SquareVM() { Position = new Point(90, 180),
                                 Color = Color.FromRgb(0x9A, 0xB8, 0x7A) },
                new SquareVM() { Position = new Point(200, 200),
                                 Color = Color.FromRgb(0xF8, 0xF9, 0x91) }
            };
    }
    

    我也喜欢上了他DraggableSquare.xaml:

    <UserControl x:Class="MvvmDraggable2.DraggableSquare"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 Width="50" Height="50"
                 MouseDown="OnMouseDown" MouseUp="OnMouseUp">
        <UserControl.Background>
            <SolidColorBrush Color="{Binding Color}"/>
        </UserControl.Background>
        <Grid/>
    </UserControl>
    

    结果是这样的:

    这就是发生的事情


    如果您希望将图像移动得更小,最简单的缩小方法是RenderTransform:

    <Canvas IsHitTestVisible="False">
        <Rectangle Opacity="0.4" Name="DraggedImageContainer" Visibility="Collapsed"
                   RenderTransformOrigin="0.5,0.5">
            <Rectangle.RenderTransform>
                <ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
            </Rectangle.RenderTransform>
        </Rectangle>
    </Canvas>
    

    与转型相同

    • 10

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5