更改ICollectionView中的项目组

时间:2015-09-16 18:05:46

标签: c# wpf mvvm-light

ICollectionView看起来像

public ICollectionView UsersCollectionView
{
    get
    {
        var view = CollectionViewSource.GetDefaultView(this);
        view.GroupDescriptions.Add(new PropertyGroupDescription("SeriesName"));
        view.SortDescriptions.Add(new SortDescription("CreationDate", ListSortDirection.Ascending));
        view.SortDescriptions.Add(new SortDescription("DocumentTypeId", ListSortDirection.Ascending));
        return view;
    }
}

我想用drag&删除以更改项目系列名称和列表视图中的位置任何想法如何执行此操作,例如

--- ScienceFiction
------------> Book1 
------------> Book2
--- History 
------------> Book3 
------------> Book4

如果在ScienceFiction中Iragedd和droped book3,那么输出应该是

--- ScienceFiction
------------> Book1 
------------> Book2
------------> Book3 
--- History 
------------> Book4

我使用xaml代码:

    <UserControl.Resources>
    <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Expander Header="{Binding Name}" IsExpanded="True">
                        <ItemsPresenter />
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<Grid>
    <ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
        <ListBox.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
        </ListBox.GroupStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>

2 个答案:

答案 0 :(得分:2)

AMH,

首先修改ListviewItem样式。它是包含列表框的每一行(datatemplate instanciation)的容器。这是一个在行级别管理拖放的好地方(不是行的控制,DataTemplate中可能有很多)。 在Visual Studio中,选择列表框,右键单击,编辑其他模板/编辑生成的项容器(ItemContainerStyle)/编辑副本

在创建的ListBoxItemStyle中,在setter中添加这三个声明:

        <EventSetter Event="ListBoxItem.DragOver" Handler="ListBoxItemDragOver"/>
        <EventSetter Event="ListBoxItem.Drop" Handler="ListBoxItemDrop"/>
        <EventSetter Event="ListBoxItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>

在ListBox上将AllowDrop属性设置为true:

<ListBox x:Name="listboxBooks" AllowDrop="True">

然后在.xaml.cs代码中实现处理程序:

    #region DnD management

    private Book sourceBook;
    private void ListBoxItemPreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton != MouseButtonState.Pressed)
            return;
        var listboxItem = sender as ListBoxItem;
        if (listboxItem == null)
            return;
        sourceBook = listboxItem.DataContext as Book;
        if (sourceBook == null)
            return;
        var data = new DataObject();
        data.SetData(sourceBook);
        // provide some data for DnD in other applications (Word, ...)
        data.SetData(DataFormats.StringFormat, sourceBook.ToString());
        DragDropEffects effect = DragDrop.DoDragDrop(listboxItem, data, DragDropEffects.Move | DragDropEffects.Copy);
    }
    private void ListBoxItemDrop(object sender, DragEventArgs e)
    {
        if (!e.Data.GetDataPresent(typeof(Book)))
            return;
        var listBoxItem = sender as ListBoxItem;
        if (listBoxItem == null)
            return;
        var targetBook = listBoxItem.DataContext as Book;
        if (targetBook != null)
        {
            viewModel.RecategorizeBook(sourceBook, targetBook.Category);
        }
        e.Handled = true;
    }
    private void ListBoxItemDragOver(object sender, DragEventArgs e)
    {
        Debug.WriteLine(e.Effects);
        if (!e.Data.GetDataPresent(typeof(Book)))
        {
            e.Effects = DragDropEffects.None;
            e.Handled = true;
        }
    }
    private void GroupItemDrop(object sender, DragEventArgs e)
    {
        if (!e.Data.GetDataPresent(typeof(Book)))
            return;
        var groupItem = sender as GroupItem;
        if (groupItem == null)
            return;
        dynamic targetGroup = groupItem.DataContext;
        if (targetGroup != null)
        {
            // here I change the category of the book
            // and refresh the view of the collectionViewSource ( see link to project zipped further)
            viewModel.RecategorizeBook(sourceBook, targetGroup.Name as String);
        }
        e.Handled = true;
    }
    #endregion

请注意,我还在处理程序的组头上实现了Drop管理。 所以处理程序需要在XAML groupstyle中声明:

<ListBox.GroupStyle>
    <GroupStyle>
        <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
                <EventSetter Event="GroupItem.Drop" Handler="GroupItemDrop"/>
                <EventSetter Event="GroupItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/>

它有效,这是完整的工作代码:http://1drv.ms/1FhBZwr

祝你有最好的代码

答案 1 :(得分:1)

不幸的是.net尚未提供“易于使用”的拖放实现。你必须自己构建一堆东西。起点将是Behavior开始拖动,ContentControl是用户可以放弃的区域。有了这些定义,您可以轻松地重用这个概念。在以下示例中,StackPanel可以“拖动”到TextBlock周围的不可见“区域”。通过这种方式,您可以手动对书籍进行排序(在鼠标指针下放置书籍之前/之后)。

如果您想将书籍放在标题上,请用DropArea将它们包围起来。你也可以实现两种方式。

您的xaml将如下所示:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
[...]
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}">
    <ListBox.GroupStyle>
        <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
    </ListBox.GroupStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <myOwn:DropArea>
                    <TextBlock Text="{Binding Name}"/>
                </myOwn:DropArea>
                <i:Interaction.Behaviors>
                    <myOwn:DragBehavior/>
                </i:Interaction.Behaviors>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

DragBehavior将如下所示:

public class DragBehavior : Behavior<FrameworkElement>
    [...]
    protected override void OnAttached()
    {
        AssociatedObject.MouseMove += AssociatedObject_MouseMove;
        AssociatedObject.MouseDown += AssociatedObject_MouseLeftButtonDown;
        AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
        base.OnAttached();
    }
    protected override void OnDetaching()
    {
        AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
        AssociatedObject.MouseDown -= AssociatedObject_MouseLeftButtonDown;
        AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
        base.OnDetaching();
    }
    protected virtual void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
    {
        if (some condition of mouse button states or mouse moves)
        {
                DataObject data = new DataObject();
                data.SetData(typeof(anyKeyType), anyData);
                data.SetData(typeof(anyOtherKeyType), anyOtherData);
                DragDrop.DoDragDrop(fe, data, DragDropEffects.Move);                
        }
    }

DropArea将如下所示:

public class DropArea : ContentControl
    [...]
    public DropArea()
    {
        DragEnter += AssociatedObjectDragEnter;
        DragLeave += AssociatedObjectDragLeave;
        DragOver += AssociatedObjectDragOver;
        IsTabStop = false;
        AllowDrop = true;
    }
    protected override void AssociatedObjectDrop(object sender, DragEventArgs e)
    {
        object o = e.Data.GetData(typeof(anyKeyType));
        //handle dropped data
    }

希望这可以帮助你。可能有任何框架或库可以解决这个问题,但这样你就可以满足自己的需求。