Search code examples
c#wpfxamlvisual-studio-2013expander

Creating an Expand All and Collapse All Buttons with Expander in WPF


I am working in Visual Studio 2013 in WPF (C#) and I have the following code to create an expander from my xml. It is currently working perfectly right now but I want to include an expand all and collapse all buttons. I have looked all over and can't seem to find a solution.

Here is where the expander is created. I know I just have to iterate through a list of items and change the Property="IsExpanded" to Value="True" to create an expand all.

       <DataTemplate x:Key="dtListTemplate" >
            <StackPanel>
                <Expander LostFocus="CollapseExpander" ExpandDirection="Down" Width="Auto">
                    <Expander.Style>
                        <Style TargetType="Expander">
                            <Setter Property="IsExpanded" Value="False" />
                            <Setter Property="Header" Value="{Binding XPath=@Name}" />
                            <Setter Property="FontWeight" Value="Bold"/>

                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsExpanded,RelativeSource={RelativeSource Self}}" Value="True">
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Expander.Style>
                    <ListBox Name="itemsList"
                        ItemsSource="{Binding XPath=UpgradeAction}"
                        ItemTemplate="{StaticResource dtListItemTemplate}"
                        SelectionChanged="listItems_SelectionChanged"
                        Style="{StaticResource styleListBoxUpgradeAction}"
                        ItemContainerStyle="{StaticResource styleListBoxItemUpgradeAction}">
                    </ListBox>
                </Expander>
            </StackPanel>
        </DataTemplate>

Here's the code that calls the DataTemplate which has information from an Xml.

<StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
            <Border Grid.Column="0" Grid.Row="0" Width="790" Height="40" Padding="5" Background="#4E87D4">
                <Label VerticalAlignment="Center" FontSize="16" FontWeight="Bold" Foreground="White">Test</Label>
            </Border>
            <Button Name="ExpandBttn" Width="100" Height="40" FontSize="16" FontWeight="Bold" Content="Expand All" DataContext="{Binding}" Click="Expand_Button_Click"/>
            <Button Name="ColapseBttn" Width="100" Height="40" FontSize="16" FontWeight="Bold" Content="Colapse All" DataContext="{Binding}" Click="Collapse_Button_Click"/>
        </StackPanel>
        <ListView Name="listItems" Grid.Column="0" Grid.Row="1" Background="Wheat"
             ItemsSource="{Binding Source={StaticResource xmldpUpgradeActions}, XPath=ActionGroup}"
             ItemTemplate="{StaticResource dtListTemplateRichards}"
             SelectionChanged="listItems_SelectionChanged">
        </ListView>
    </StackPanel>

Here's what I tried in the .cs file for the expand all portion.

  private void Expand_Button_Click(object sender, RoutedEventArgs e)
  {
      foreach(var item in listItems.Items)
      {
          var listBoxItem = listItems.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
          var itemExpander = (Expander)GetExpander(listBoxItem);
          if (itemExpander != null)
              itemExpander.IsExpanded = true;
      }
  }

  private static DependencyObject GetExpander(DependencyObject container)
  {
      if (container is Expander) return container;

      for (var i = 0; i < VisualTreeHelper.GetChildrenCount(container); i++)
      {
          var child = VisualTreeHelper.GetChild(container, i);

          var result = GetExpander(child);
          if (result != null)
          {
              return result;
          }
      }

      return null;
  }

Any help is greatly appreciated!


Solution

  • Is xmldpUpgradeActions a CollectionViewSource?

    Whatever class is in the collection, it should implement INotifyPropertyChanged.

    Give it an IsExpanded property that raises PropertyChanged in its setter when its value changes, and bind that to Expander.IsExpanded in the template:

    <Expander 
        IsExpanded="{Binding IsExpanded}"
        LostFocus="CollapseExpander" 
        ExpandDirection="Down" 
        Width="Auto">
    

    Write a command that loops through all the items in the collection and sets item.IsExpanded = false; on each one.