wpf sorting listbox groupstyle

Sort and Group ListItems en WPF ListBox- GroupItem contraer y expandir



sorting groupstyle (1)

La solución no es perfecta. Como dije, es mejor usar ViewModels con su propia agrupación, pero requerirá mucho más código.

Necesitas dos controladores de eventos:

private Dictionary<string, bool?> expandStates = new Dictionary<string, bool?>(); private void Grid_Loaded(object sender, RoutedEventArgs e) { var grid = (Grid)sender; var dc = grid.DataContext as CollectionViewGroup; var groupName = (string)dc.Name; //If the dictionary contains the current group, retrieve a saved state of the group if (this.expandStates.ContainsKey(groupName)) { var btn = (ToggleButton)grid.FindName("btnShowHide"); btn.IsChecked = this.expandStates[groupName]; } //Else add default state else this.expandStates.Add(groupName, true); } private void btnShowHide_Click(object sender, RoutedEventArgs e) { var btn = (ToggleButton)sender; var dc = (CollectionViewGroup)btn.DataContext; var groupName = (string)dc.Name; //Loaded event is fired earlier than the Click event, so I''m sure that the dictionary contains the key this.expandStates[groupName] = btn.IsChecked; //Save the current state }

Están vinculados con controles aquí:

<ControlTemplate TargetType="{x:Type GroupItem}"> <Grid Loaded="Grid_Loaded">

y aquí:

<ToggleButton x:Name="btnShowHide" Click="btnShowHide_Click" IsChecked="True" Margin="3.5" />

Si define Template for GroupItem en algún lugar de un diccionario externo, debe usar UserControl con el fin de tener acceso a código subyacente.

Ordeno y agrupo elementos de la lista, uso CollectioView para este propósito.

Desde la clase de vista de vista I, la colección de enlaces en la propiedad ItemSource de ListBox, aquí está.

public BindableCollection<UserInfo> Friends { get { return _friends; } set { _friends = value; NotifyOfPropertyChange(() => Friends); } }

Los elementos de ListBox son tipo de UserInfo.

Cuando inicializo ListBox, clasifico y grupo elementos con este método.

private ICollectionView _currentView; //... private void SortContactList() { _currentView = CollectionViewSource.GetDefaultView(Friends); _currentView.GroupDescriptions.Add(new PropertyGroupDescription("TextStatus")); _currentView.SortDescriptions.Add(new SortDescription("TextStatus", ListSortDirection.Ascending)); _currentView.SortDescriptions.Add(new SortDescription("Nick", ListSortDirection.Ascending)); }

TextStatus y Nick son propiedades de la clase userInfo.

Yo uso en Listbox GroupStyle. Aquí está:

<Style x:Key="MessengerView_ToogleBtn" TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Image x:Name="img" Source="/images/icons/Collapse.png" /> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="False"> <Setter TargetName="img" Property="Source" Value="/images/icons/Expand.png" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <GroupStyle> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupItem}"> <ControlTemplate.Triggers> <DataTrigger Binding="{Binding Path=IsBottomLevel}" Value="True"> <Setter TargetName="gridTemplate" Property="Grid.Background" Value="White" /> </DataTrigger> </ControlTemplate.Triggers> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Grid Background="Black" x:Name="gridTemplate" Height="26" VerticalAlignment="Center"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="45" /> </Grid.ColumnDefinitions> <ToggleButton x:Name="btnShowHide" IsChecked="True" Style="{StaticResource MessengerView_ToogleBtn}"/> <TextBlock Style="{StaticResource MessengerView_LbGroupHeader_TextBlock}" Text="{Binding Path=Name}" Grid.Column="1"/> <TextBlock TextAlignment="Left" Style="{StaticResource MessengerView_LbGroupHeader_TextBlock}" Grid.Column="2" Text="{Binding Path=ItemCount}"/> </Grid> <ItemsPresenter Visibility="{Binding ElementName=btnShowHide, Path=IsChecked, Converter={StaticResource booleanToVisibilityConverter}}" Margin="3,3,3,3" Grid.Row="1" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> </GroupStyle>

Si ejecuto la aplicación, mira en esta imagen.

1.

Edito la propiedad de fuente de ListBox, (agregar, eliminar, actualizar), después del cuadro de lista editado llamo al método Refresh en CollectionView.

_currentView.Refresh();

El problema es que GroupItem se colapsó y llamé al método Refresh en todos los GroupItem se expandieron.

Por ejemplo.

GroupItem 1 está colapsado.

GroupItem 2 se expone.

GroupItem 3 está colapsado.

Antes de llamar a Refresh ListBox se ven como en esta imagen:

Llamo al método Refresh en CollectionView y todos los GroupItems están expandidos. Me gustaría mantener el estado original, ¿cómo puedo lograr esto?

Después de llamar a Refresh Lisbox se ve como en la primera imagen en la parte superior.