Using Expander controls in C# / WPF

A short post demonstrating how to use expander controls in WPF, to create a list of collapsible / expandable menu items in your C# WPF application

Create a new Visual Studio application

Create a View Model class for your main window

MainWindowViewModel.cs

using System.Collections.Generic;

namespace ExpanderExample
{
   public class ApplicationListItem
   {
      public ApplicationListItem(string name, string openButtonText, string updateButtonText,
         bool updateButtonVisibility = false, bool progressVisibility = true)
      {
         Name = name;
         OpenButtonText = openButtonText;
         UpdateButtonText = updateButtonText;
         UpdateButtonVisibility = updateButtonVisibility;
         ProgressVisibility = progressVisibility;
      }

      public string Name { get; set; }
      public string OpenButtonText { get; set; }
      public string UpdateButtonText { get; set; }
      public bool UpdateButtonVisibility { get; set; }
      public bool ProgressVisibility { get; set; }
   }

   public class ListItem
   {
      public ListItem(string title)
      {
         Title = title;
      }

      public string Title { get; set; }
      public List<ApplicationListItem> ListItems { get; set; } = new List<ApplicationListItem>();

      public void AddListItem(ApplicationListItem listItem)
      {
         ListItems.Add(listItem);
      }
   }

   public class MainWindowViewModel
   {
      public MainWindowViewModel()
      {
         var listItem1 = new ListItem("CMM");
         var appListItem1 = new ApplicationListItem("CMM - Local (English)", "Open", "Update", false, false);
         var appListItem2 = new ApplicationListItem("CMM - Local (German)", "Open", "Update", false, false);
         var appListItem3 = new ApplicationListItem("CMM - Local (Japanese)", "Open", "Update", true);
         listItem1.AddListItem(appListItem1);
         listItem1.AddListItem(appListItem2);
         listItem1.AddListItem(appListItem3);
         Items.Add(listItem1);

         var listItem2 = new ListItem("Sales Aid");
         var appListItem4 = new ApplicationListItem("Sales Aid - Local (English)", "Open", "Update", true, false);
         listItem2.AddListItem(appListItem4);
         Items.Add(listItem2);
      }

      public List<ListItem> Items { get; } = new List<ListItem>();
   }
}

So that we may hide/collapse/make visible individual controls in our expandable items list, set the boolean to visibility conversion in app.xaml

App.xaml

<Application x:Class="ExpanderExample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ExpanderExample"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
    </Application.Resources>
</Application>

Update the main window xaml to contain our expander control:

MainWindow.xaml

<Window x:Class="ExpanderExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ExpanderExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <ItemsControl
        Name="ItemsList"
        ItemsSource="{Binding Items}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Expander Header="{Binding Title}">
                        <ItemsControl
                            Name="icTodoList"
                            ItemsSource="{Binding ListItems}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="40" />
                                            <RowDefinition Height="*" />
                                        </Grid.RowDefinitions>

                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="300" />
                                                <ColumnDefinition Width="*" />
                                            </Grid.ColumnDefinitions>

                                            <TextBlock
                                                VerticalAlignment="Center" Text="{Binding Name}" />

                                            <Grid Column="1">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="*" />
                                                    <ColumnDefinition Width="*" />
                                                </Grid.ColumnDefinitions>

                                                <Button
                                                    Visibility="{Binding UpdateButtonVisibility, Converter={StaticResource BoolToVisibilityConverter}}"
                                                    Name="Update"
                                                    Width="80"
                                                    Height="30"
                                                    HorizontalAlignment="Right"
                                                    Content="{Binding UpdateButtonText}" />

                                                <Button
                                                    Name="OpenInstallPauseResume"
                                                    Grid.Column="1"
                                                    Width="80"
                                                    Height="30"
                                                    HorizontalAlignment="Right"
                                                    Content="{Binding OpenButtonText}" />
                                            </Grid>
                                        </Grid>

                                        <Grid Grid.Row="1">
                                            <ProgressBar
                                                Visibility="{Binding ProgressVisibility, Converter={StaticResource BoolToVisibilityConverter}}"
                                                Height="20" />
                                        </Grid>
                                    </Grid>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Expander>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

On building and running the application see that the window contains the two expander controls as shown:

On expanding the expander controls see that thse now contain the ItemsControl elements (buttons, title strings, progress bars etc), which are visible according to the values set during the initialisation of the main window View Model class.