Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

change the group of item in ICollectionView

Tags:

c#

wpf

mvvm-light

I have ICollectionView looks like

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;
    }
}

I want to use drag & drop to change the item Series Name , and location on the list view any idea how to do that for example

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

if Idraged and droped book3 in ScienceFiction the output should be

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

I use xaml code like this :

    <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>

like image 421
AMH Avatar asked Sep 16 '15 18:09

AMH


1 Answers

AMH,

First modify the ListviewItem Style. It is the container that contains every line (datatemplate instanciation) of the listbox. It is a good place to manage Drag and Drop at the line level ( not a control of a line, there could be many in the DataTemplate). In Visual Studio, select the listbox, right click, Edit additional templates/Edit Generated Item Container(ItemContainerStyle)/Edit a copy

In the ListBoxItemStyle created, add those three declarations amongst the setters :

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

Set the AllowDrop property to true on the ListBox :

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

Then implement the handlers in the .xaml.cs code :

    #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

Note that I also implemented Drop management on the group header in the handlers. So the handler needs to be declared in the XAML groupstyle :

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

It works, here is full working code : http://1drv.ms/1FhBZwr

Wish you the best possible code

like image 67
Emmanuel DURIN Avatar answered Sep 25 '22 14:09

Emmanuel DURIN