Multiple Expander have to collapse if ONE is expanded

前端 未结 7 980
南笙
南笙 2020-12-08 22:42

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

相关标签:
7条回答
  • 2020-12-08 23:26

    Try the Accordion control from WPF Toolkit - February 2010 Release

    http://www.dotnetspark.com/kb/1931-accordion-wpf-toolkit-tutorial.aspx

    Sample code:

    <my:Accordion  x:Name="accordion1" VerticalAlignment="Top" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" SelectionMode="ZeroOrOne">
            <my:AccordionItem Header="First Header" Content="First Content"/>
            <my:AccordionItem Header="Second Header">
                <StackPanel Height="300">
                <TextBlock Text="Second Content" /></StackPanel>
            </my:AccordionItem>
            <my:AccordionItem>
                <my:AccordionItem.Header>
                    <TextBox Text="Third Item" />
                </my:AccordionItem.Header>
                <StackPanel Height="300">
                    <TextBlock Text="Third Item" />
                </StackPanel>
            </my:AccordionItem>
            <my:AccordionItem>
                <my:AccordionItem.Header>
                    <TextBlock Text="Fourth Item" />
                </my:AccordionItem.Header>
                <StackPanel Height="300">
                    <TextBlock Text="Third Item" />
                </StackPanel>
            </my:AccordionItem>
        </my:Accordion>
    
    0 讨论(0)
  • 2020-12-08 23:30

    Just setting the Lost focus seems to be the easiest way to do this.

    Xaml:

    <Expander LostFocus="CollapseExpander" ExpandDirection="Down" Width="175">
        <ListBox Height="265" Margin="0,5,0,10">
        </ListBox>
    </Expander>
    

    VB:

    Private Sub CollapseExpander(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    
     sender.IsExpanded = False
    
    End Sub
    
    0 讨论(0)
  • 2020-12-08 23:31

    @wassim-azirar asked to the accepted answer:

    How can I expand 'Expander 1' at the application Startup ?

    I added in the ViewModel:

    SelectedExpander = "1";
    

    Because of the fact, that the "1" is not the same object as the "1" in XAML this will not work, so I changed decyclone's answer like this:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (string)value == (string)parameter;
    }
    

    The answer of decyclone was very helpful for me - Thanks.
    So I would like to share my experience if someone needs it.

    0 讨论(0)
  • 2020-12-08 23:38

    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.

    0 讨论(0)
  • 2020-12-08 23:40

    this is how I did it:

    1) added a StackPanel and MUST add a name tag attribute (as this is the master).

    StackPanel Name="StackPanel1"

    2) add as many Expanders as you need (1 to 100's if needed) each MUST have:-

    Expanded="Expander_Expanded"

    added (notice all have 100% the same wording).

    3) no other details need to match on each ( no height's names etc.. needed).

    Xaml:

    <StackPanel Name="StackPanel1">
    <Expander Header="Expander 1" Expanded="Expander_Expanded">
        <TextBlock>Expander 1</TextBlock>
    </Expander>
    <Expander Header="Expander 2" Expanded="Expander_Expanded">
        <TextBlock>Expander 2</TextBlock>
    </Expander>
    <Expander Header="Expander 3" Expanded="Expander_Expanded" >
        <TextBlock>Expander 3</TextBlock>
    </Expander>
    <Expander Header="Expander 4" Expanded="Expander_Expanded" >
        <TextBlock>Expander 4</TextBlock>
    </Expander>
    

    4) To control the open/close of all "Expanders" on the named "StackPanel1" StackPanel you only need to add the below code once.

    VB code-behind:

    Private Sub Expander_Expanded(sender As Object, e As RoutedEventArgs)
        For Each exp As Expander In StackPanel1.Children
            If exp IsNot sender Then
                exp.IsExpanded = False
            End If
        Next
    End Sub
    

    5)Now you can change/add what content, button's, textbox's etc.. you need just do not change 2 things 1, "StackPanel Name" 2, "Expander Expanded" without updating the code-behind else things will not work.

    Hope this information is helpful to you.

    What's happening?

    1) All panels are parents and all controls on that panel are children,

    2) All controls are children of a parent panel.

    3) A class deals with one call at a time.

    4) The class deals with child.

    6) The class move to next child.

    7) Stops once all children have been asked.

    So the pseudo code is like this:

    1) Listen for a child’s named x

    2) Ask each child in parents list of children

    3) If child is not calling then

    4) Child is expanded is false

    5) End asking that child

    6) Move to next child and ask again

    7) Until all children have been asked

    0 讨论(0)
  • 2020-12-08 23:42

    Use MVVM and bind the IsExpanded property to a boolean flag on your view models. When one is updated to true, set all the others to false.

    0 讨论(0)
提交回复
热议问题