ItemsControl的拖放 [英] ItemsControl Drag and Drop

查看:163
本文介绍了ItemsControl的拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ItemsControl与绑定到整数的ObservableCollection一个DataTemplate

 < ItemsControl的名称=DimsContainer 的ItemTemplate ={StaticResource的DimensionsTemplate}> 
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< StackPanel的方向=横向/>
< / ItemsPanelTemplate>
< /ItemsControl.ItemsPanel>
< / ItemsControl的>

和在Windows资源:

 < Window.Resources> 
<的DataTemplate X:键=DimensionsTemplate>
< TextBlock的文本={结合}
填充=5
VerticalAlignment =中心
字号=32/>
< / DataTemplate中>
< /Window.Resources>



我试图实现与ItemsControl的内拖放项目的能力(即能够重新排序整数)。有没有人对如何做一个简单的例子?我迷上了PreviewMouseMove,的dragenter和Drop事件。问题是,我无法弄清楚如何确定哪个项目被拖动以及它拖动到。如此看来,整个ItemsControl的被传递到事件。


解决方案

下面是一个例子,如何我已经做到了。



XAML:

 < Window.DataContext> 
<局部:MyViewModel />
< /Window.DataContext>

<网格和GT;
<&的ScrollViewer GT;
< ListView控件的ItemsSource ={结合迈德特}的Horizo​​ntalAlignment =拉伸NAME =列表视图ScrollViewer.PanningMode =VerticalOnly>
< ListView.ItemTemplate>
<&DataTemplate的GT;
<按钮内容={结合}
命令={结合DataContext.MyCommand,的RelativeSource = {的RelativeSource AncestorType =的ItemsControl}
CommandParameter ={结合}
保证金=5 2WIDTH =150HEIGHT =50
字号=30/>
< / DataTemplate中>
< /ListView.ItemTemplate>
< ListView.Resources>
<风格的TargetType =按钮>
< EventSetter事件=PreviewMouseMove处理器=PreviewMouseMove/>
< EventSetter事件=滴处理程序=滴/>
< setter属性=的AllowDropVALUE =真/>
< /样式和GT;
< /ListView.Resources>
< /&的ListView GT;
< /&的ScrollViewer GT;
< /网格和GT;





视图模型:

 类MyViewModel 
{
公共MyViewModel()
{
MyCommand =新ICommandImplementation();
}

公众的ObservableCollection<串GT;迈德特
{
得到
{
返回新的ObservableCollection<串>(新的String [] {
一,二,三,四,十二五,六个一,七,八,九,十,
十一,十二条,十三,十四,十五, 十六条,十七,十八,古诗十九首,廿
});
}
}

公众的ICommand MyCommand {搞定;私人集; }

私有类ICommandImplementation:ICommand的
{
公共BOOL CanExecute(对象参数){返回true; }
公共事件的EventHandler CanExecuteChanged;
公共无效执行(对象参数){System.Windows.MessageBox.Show(按钮,点击!+(参数??)的ToString()); }
}
}



活动:

 私人无效丢弃(对象发件人,DragEventArgs E)
{
变种来源= e.Data.GetData(源)作为字符串;
如果(来源!= NULL)
{
INT newIndex = listview.Items.IndexOf((发件人为按钮).Content);
无功名单= listview.ItemsSource作为的ObservableCollection<字符串取代;
list.RemoveAt(list.IndexOf(源));
list.Insert(newIndex,源);
}
}

私人无效PreviewMouseMove(对象发件人,MouseEventArgs E)
{
如果(e.LeftButton == MouseButtonState.Pressed)
{
Task.Factory.StartNew(新动作(()=>
{
的Thread.Sleep(500);
App.Current.Dispatcher.BeginInvoke(新操作(()=>
{
如果(e.LeftButton == MouseButtonState.Pressed)
{
VAR数据=新的DataObject();
数据。的SetData(源,(如发送按钮).Content);
DragDrop.DoDragDrop(发件人为DependencyObject的,数据,DragDropEffects.Move);
e.Handled = TRUE;
$} b $ b}),NULL);
}),CancellationToken.None);
}
}



上面的例子是一个有点复杂原因的每一个项目列表按钮按钮 点击我也有做一些事情。你的情况是比较容易的。




拖放放大器;掉落混乱可能是许多开发人员混淆。但低于
是一些关键点是如何做到这一点:




  1. 使用 PreviewMouseMove 事件真正开始一拖在处理程序使用 DragDrop.DoDragDrop 活动筹集的DragDrop 相关
    事件和光标发件人的说法是,有
    在这种情况下,目前拍摄的鼠标的UIElement 是$ B元素$ b被拖


  2. 使用的dragenter &放大器。 的dragover 事件,如果想改变在其上鼠标正在拖动视觉元素。 发件人
    的说法是,目前已经拖过/这个元素只是
    结束了形势的拖累。


  3. 使用挂断事件来处理的下降因素。 发件人参数是在其上落发生的元素。


  4. 使用数据对象对象传递这些事件之间的信息。之类的的SetData 方法被用来在这个添加数据。这种方法
    有两个参数,他们的工作就像键 - 值对。一旦设置你
    可以通过使用
    获得的DragDrop 的下一个称为事件这一数据的GetData 通过将作为参数的方法。 (即
    e.Data.GetData(源)





这里是一个相对的帖子。


I have an ItemsControl with a DataTemplate that is bound to an ObservableCollection of integers.

<ItemsControl Name="DimsContainer" ItemTemplate="{StaticResource DimensionsTemplate}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

And in the Windows Resources:

<Window.Resources>
    <DataTemplate x:Key="DimensionsTemplate" >
        <TextBlock Text="{Binding}"
                       Padding="5"
                       VerticalAlignment="Center"
                       FontSize="32"/>
    </DataTemplate>
</Window.Resources>

I'm trying to implement the ability to drag and drop items within the ItemsControl (i.e. to be able to reorder the integers). Does anyone have a simple example of how to do this? I hooked up the PreviewMouseMove, DragEnter and Drop events. The problem is that I can't figure out how to determine which item is being dragged and where it is dragged to. It seems that the entire ItemsControl gets passed into the events.

解决方案

Here is an example how I've done it.

XAML:

<Window.DataContext>
    <local:MyViewModel />
</Window.DataContext>

<Grid>
    <ScrollViewer>
        <ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch" Name="listview" ScrollViewer.PanningMode="VerticalOnly">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding}"
                        Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
                        CommandParameter="{Binding}"
                        Margin="5 2" Width="150" Height="50"
                        FontSize="30" />
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Resources>
                <Style TargetType="Button">
                    <EventSetter Event="PreviewMouseMove" Handler="PreviewMouseMove" />                        
                    <EventSetter Event="Drop" Handler="Drop" />                       
                    <Setter Property="AllowDrop" Value="True" />                        
                </Style>
            </ListView.Resources>
        </ListView>
    </ScrollViewer>
</Grid>

ViewModel:

 class MyViewModel
{
    public MyViewModel()
    {
        MyCommand = new ICommandImplementation();
    }

    public ObservableCollection<string> MyData
    {
        get
        {
            return new ObservableCollection<string>(new string[]{
            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
            "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
            });
        }
    }

    public ICommand MyCommand { get; private set; }

    private class ICommandImplementation : ICommand
    {
        public bool CanExecute(object parameter) { return true; }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); }
    }
}

Events:

 private void Drop(object sender, DragEventArgs e)
    {
        var source = e.Data.GetData("Source") as string;
        if (source != null)
        {
            int newIndex = listview.Items.IndexOf((sender as Button).Content);
            var list = listview.ItemsSource as ObservableCollection<string>;
            list.RemoveAt(list.IndexOf(source));
            list.Insert(newIndex, source);
        }
    }

    private void PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            Task.Factory.StartNew(new Action(() =>
                {
                    Thread.Sleep(500);
                    App.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            if (e.LeftButton == MouseButtonState.Pressed)
                            {                                    
                                var data = new DataObject();
                                data.SetData("Source", (sender as Button).Content);
                                DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move);
                                e.Handled = true;
                            }
                        }), null);
                }), CancellationToken.None);
        }           
    }

Above example is a little complex cause every item of list is a Button and on Button click I also have to do something. Your case is relatively easy.

Drag & Drop confusing can be confusing for many developers. But below are the some key points how to do it:

  1. Use PreviewMouseMove event to actually start a drag and in handler use DragDrop.DoDragDrop event to raise DragDrop related events and Cursors. sender argument is the element that has captured the mouse currently in this case the UIElement that is being dragged.

  2. Use DragEnter & DragOver event if want to change the visual of element over which the Mouse is currently dragging. sender argument is the element that has currently dragged over / that just ended drag over situation.

  3. Use Drop event to handle the dropped element. sender argument is the element on which the Drop happened.

  4. Use DataObject object to pass info between these events. SetData method of the class is used to add data in this. This method has two arguments, and they work like key-value pair. Once set you can get this data in next called event of DragDrop by using GetData method by passing the key as argument. (i.e. e.Data.GetData("Source"))

Here is a relative post.

这篇关于ItemsControl的拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆