Multiple Expander have to collapse if ONE is expanded

Elisabeth picture Elisabeth · Dec 15, 2010 · Viewed 20.9k times · Source

Having 4 Expander controls. When one expander is expanded how can I make all others collapse/close?

Answer

decyclone picture decyclone · Dec 15, 2010

Try out following code:

XAML:

        <StackPanel Name="StackPanel1">
            <StackPanel.Resources>
                <local:ExpanderToBooleanConverter x:Key="ExpanderToBooleanConverter" />
            </StackPanel.Resources>
            <Expander Header="Expander 1"
                      IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=1}">
                <TextBlock>Expander 1</TextBlock>
            </Expander>
            <Expander Header="Expander 2"
                      IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=2}">
                <TextBlock>Expander 2</TextBlock>
            </Expander>
            <Expander Header="Expander 3"
                      IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=3}">
                <TextBlock>Expander 3</TextBlock>
            </Expander>
            <Expander Header="Expander 4"
                      IsExpanded="{Binding SelectedExpander, Mode=TwoWay, Converter={StaticResource ExpanderToBooleanConverter}, ConverterParameter=4}">
                <TextBlock>Expander 4</TextBlock>
            </Expander>
        </StackPanel>

Converter:

public class ExpanderToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (value == parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (System.Convert.ToBoolean(value)) return parameter;
        return null;
    }
}

ViewModel:

public class ExpanderListViewModel
{
    public Object SelectedExpander { get; set; }
}

Initialization

StackPanel1.DataContext = new ExpanderListViewModel();

Explanation:

In XAML we have 4 expanders. They all inherit a ViewModel (of type ExpanderListViewModel) from container StackPanel through DataContext.

They all bind to single property on ViewModel class. And have defined a unique index for themselves using ConverterParameter in binding. That index gets saved in SelectedExpander property whenever you expand an expander. And using that index, the Converter returns true if the stored index matches with given index and false if stored index does not match.

Put a breakpoint in Convert and ConvertBack methods of Converter class and you will see what is going on.