I am using popular code to sort and group listview items. Sorting and grouping work perfect. The problem is when user clicks on column header for sorting then all groups become i.e. expanded or collapsed (that depends from Expander IsExpanded="False") What I would need is sorting of columns leaving expanders in their current state: some expanded, some collapsed. I checked also some sample projects but all of them have same behaviour. Any ideas, is it doable ? Thanks in advance!
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="False" BorderBrush="#FFA4B97F"
BorderThickness="0,0,0,1" >
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"
Margin="5,0" Width="Auto"/>
<TextBlock FontWeight="Bold"
Text="{Binding Path=ItemCount}"/>
<TextBlock FontWeight="Bold" Text=" Items"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
ICollectionView view = CollectionViewSource.GetDefaultView(dataSet.Tables[0]);
view.GroupDescriptions.Add(new PropertyGroupDescription("NameOfColumnForGrouping"));
listViewOpportunitiesHistory.ItemsSource = view;
Sorting:
listViewOpportunitiesHistory.Items.SortDescriptions.Add(new SortDescription(field, newDir));
Here is how I solved my problem:
<ListView x:Name="listViewOpportunitiesHistory" ItemsSource="{Binding}" AlternationCount="2"
IsTextSearchEnabled="False" IsSynchronizedWithCurrentItem="True" >
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Grid x:Name="grid_ControlTemplate_listViewOpportunitiesHistory" Loaded="grid_ControlTemplate_listViewOpportunitiesHistory_Loaded">
<Expander BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1"
x:Name="expanderControlTemplate" Expanded="expanderExpandCollapse_Expanded" Collapsed="expanderExpandCollapse_Collapsed" >
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"
Margin="5,0" Width="Auto"/>
<TextBlock FontWeight="Bold"
Text="{Binding Path=ItemCount}"/>
<TextBlock FontWeight="Bold" Text=" Items"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="Auto" x:Name="listViewOpportunitiesHistoryColumn_Time" >
<GridViewColumnHeader Click="SortClickHistory" Tag="Time" Content=" Time " x:Name="listViewOpportunitiesHistoryColumnHeader_Time" />
<GridViewColumn.CellTemplate >
<DataTemplate>
<Border BorderBrush ="Gray" BorderThickness="0,0,1,0" Margin="-6,0,-6,0">
<Grid Margin="6,0,6,0" >
<TextBlock Text="{Binding Path=Time, StringFormat='yyyy-MM-dd HH:mm:ss.fff'}" Grid.Column ="0" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" ToolTipService.ToolTip="{Binding Path=Time}" />
</Grid>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="Auto" x:Name="listViewOpportunitiesHistoryColumn_AOValue" >
<GridViewColumnHeader Click="SortClickHistory" Tag="AOValue" Content=" AO Value " x:Name="listViewOpportunitiesHistoryColumnHeader_AOValue" />
<GridViewColumn.CellTemplate >
<DataTemplate>
<Border BorderBrush ="Gray" BorderThickness="0,0,1,0" Margin="-6,0,-6,0">
<Grid Margin="6,0,6,0" >
<TextBlock Text="{Binding Path=AOValue}" Grid.Column ="0" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" ToolTipService.ToolTip="{Binding Path=AOValue}" />
</Grid>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Code behind:
private Dictionary<string, bool?> expandStates = new Dictionary<string, bool?>();
private void grid_ControlTemplate_listViewOpportunitiesHistory_Loaded(object sender, RoutedEventArgs e)
{
var grid = (Grid)sender;
var dc = grid.DataContext as CollectionViewGroup;
var groupName = (string)dc.Name.ToString();
//If the dictionary contains the current group, retrieve a saved state of the group
if (this.expandStates.ContainsKey(groupName))
{
var expander = (Expander)grid.FindName("expanderControlTemplate");
//btn.IsExpanded = this.expandStates[groupName];
if (this.expandStates[groupName] == true)
{
expander.IsExpanded = true;
}
if (this.expandStates[groupName] == false)
{
expander.IsExpanded = false;
}
}
}
private void expanderExpandCollapse_Collapsed(object sender, RoutedEventArgs e)
{
var expander = (Expander)sender;
var dc = (CollectionViewGroup)expander.DataContext;
var groupName = (string)dc.Name.ToString();
//Loaded event is fired earlier than the Click event, so I'm sure that the dictionary contains the key
this.expandStates[groupName] = expander.IsExpanded; //Save the current state
}
private void expanderExpandCollapse_Expanded(object sender, RoutedEventArgs e)
{
var expander = (Expander)sender;
var dc = (CollectionViewGroup)expander.DataContext;
var groupName = (string)dc.Name.ToString();
//Loaded event is fired earlier than the Click event, so I'm sure that the dictionary contains the key
this.expandStates[groupName] = expander.IsExpanded; //Save the current state
}
I get the data from DataSet:
ICollectionView view = CollectionViewSource.GetDefaultView(dataSet.Tables[0]);
view.GroupDescriptions.Add(new PropertyGroupDescription(FXH.string_GroupBy_OpportunitiesHistory));
listViewOpportunitiesHistory.ItemsSource = view;
This solution is based on Sort and Group ListItems in a WPF ListBox- GroupItem collapse and expand