WPF ListView/Gridview allow users to select multip

2019-08-30 10:32发布

问题:

I have a WPF ListView/GridViwe in a MVVM application. GridView is bound to a List in the ViewModel.

The requirement is that the users should be able to select multiple rows of the gridview, right-click on it and see a context menu "Group These Together". Once selected, all these items should be collapsed into one group with a expander or + sign added at the beginning.

Can somebody please help me in getting this working?

回答1:

I was working on similar problem, but I had to group items by their let's say name. What I've done was create DataTrigger or MultiDataTrigger depending on your data requirements and then when conditions are true i.e. item selected change the container for GroupItem. What I mean is when you create your list view, you have to create it with grouped view, which btw is not grouped as you can declare it without expander and just use the StackPanel. After that you need 3 lines of Code to set the grouping. Here is an example for you: MAIN.xaml

<ListView 
                ScrollViewer.CanContentScroll="False" 
                x:Name="lsvProducts" 
                ItemsSource="{Binding Products, NotifyOnSourceUpdated=True}" 
                MouseDown="lsvProducts_MouseDown">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Width="Auto" Header="Code" DisplayMemberBinding="{Binding ID}"/>
                        <GridViewColumn Width="Auto" Header="Description" DisplayMemberBinding="{Binding Desc}"></GridViewColumn>
                        <GridViewColumn Width="Auto" Header="Qty" DisplayMemberBinding="{Binding Qty}"></GridViewColumn>
              </GridView>
                </ListView.View>
                <ListView.GroupStyle>
                    <GroupStyle ContainerStyle="{StaticResource GroupedView}"/>
                </ListView.GroupStyle>
            </ListView>

As you can see I have declared an empty container for the grouped style, reson why is because you can't assign it without previous declaration. After this declaration you need this in your generic.xaml

<Style x:Key="GroupedView" TargetType="{x:Type GroupItem}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=chbx, Path=IsChecked}" Value="True">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Expander IsExpanded="False">
                                <Expander.Header>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
                                        <TextBlock Text="{Binding ItemCount}" FontSize="16" Foreground="DimGray" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
                                        <TextBlock Text=" item(s)" FontSize="16" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
                                    </StackPanel>
                                </Expander.Header>
                                <ItemsPresenter />
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>

After you declared your style for the true value you need to declare one for without expander

<!--This goes in the same style as the prevoius sample code -->
    <DataTrigger Binding="{Binding ElementName=chbx, Path=IsChecked}" Value="False">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <StackPanel>
                                    <ItemsPresenter />
                                </StackPanel>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>

Next step is to define the grouping:

//lsvProducts is our ListView
view = (CollectionView) CollectionViewSource.GetDefaultView(lsvProducts.ItemsSource);
//in the creation parameter you should put field that you want to group by :-)
PropertyGroupDescription grouping = new PropertyGroupDescription("FieldToGroupBy");
view.GroupDescriptions.Add(grouping);

Which should apper in your ViewModel. Good luck! Let us know if you need any more help, I'll try my best with my English ;-)

EDIT

I forgot to mention when you assign the grouping you need to check the number of groups already in the collection and only apply it when there is non or 0, otherwise you'll apply the grouping multiple times and the expander will be repeeated in the result window as many times as you added the grouping :-)



回答2:

What in my mind to select multiple row Ctrl+click

It will select multiple row and on right click open a context menu after setting its Isopen to true

You should also bind selected item to list and Use this item to make an expander