سؤال

My view works like this. I have an Observable Collection, which contains objects put on the list. By clicking on any item, I can open an expander related to that item. Here is the question: How can I collapse (close) the previously opened expander when I open another one? I don't want to have a situation where multiple expanders are opened at the same time.

My WPF code looks like this:

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <controls:Pivot>
            <controls:PivotItem>
                <ListBox x:Name="PizzaList" SelectionChanged="PizzaList_SelectionChanged" IsSynchronizedWithCurrentItem="false" >
                    <ListBox.ItemTemplate>
                        <DataTemplate x:Name="template">

                            <toolkit:ExpanderView Header="{Binding Name}" x:Name="expander" Style="{StaticResource ExpanderViewStyle}">
                                <toolkit:ExpanderView.Items>
                                   <!--first stack panel would contain all elements which would be showed 
                                    after clicking on listbox item-->
                                    <StackPanel Margin="20,0,0,0" Orientation="Vertical">
                  <!-- here is content of expander-->                    
                                    </StackPanel>
                                </toolkit:ExpanderView.Items>
                                <toolkit:ExpanderView.Expander>
                                    <TextBlock Text="{Binding Name_of_ingredients}" Width="500"></TextBlock>
                                </toolkit:ExpanderView.Expander>
                            </toolkit:ExpanderView>


                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </controls:PivotItem>
        </controls:Pivot>
    </Grid>

I could have a static number of expanders if I were working with a fixed dataset, but when the expander is in a data template, the number of items could change. I'm not sure how to solve this.

هل كانت مفيدة؟

المحلول

I think this can help:

private void PizzaListSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    foreach (var item in PizzaList.Items)
    {
        var listBoxItem =
            PizzaList.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
        var itemExpander = (Expander) GetExpander(listBoxItem);
        if (itemExpander != null)
            itemExpander.IsExpanded = false;
    }
}

and search of Expander

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;
}

More ways to find controls in this question How can I find WPF controls by name or type?

نصائح أخرى

I hope this looks ok, haven't posted code before.

I found this solution to expanding/collapsing listboxitems. The grid below is what holds my content. Its height is the contents actual height within the stackpanel (x:Name="stack") and stored in the Grid's Tag property. the DataTrigger animates the Tag. The custom:XSButton comes from Andy L's CustomControls, and acts as a ToggleButton. Just need this converter for the Grid height.

    public class MultiplyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double result = 1.0;
        for (int i = 0; i < values.Length; i++)
        {
            if (values[i] is double)
                result *= (double)values[i];
        }

        return result;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new Exception("Not implemented");
    }
}

The Grid

                <Grid x:Name="Grid" Grid.ColumnSpan="3" Grid.Row="1" >
                    <Grid.Tag>
                        <System:Double>0.0</System:Double>
                    </Grid.Tag>
                    <Grid.Height>
                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                            <Binding Path="ActualHeight" ElementName="stack"/>
                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                        </MultiBinding>
                    </Grid.Height>
                    <custom:XSButton IsChecked="{Binding 
                      RelativeSource={RelativeSource FindAncestor, 
                      AncestorType={x:Type ListBoxItem}},
                      Path=IsSelected}" Background="Transparent" BorderThickness="0" BorderBrush="Transparent"
                                      ClickMode="Press" 
                                    Foreground="Transparent" Style="{DynamicResource XSButtonStyle1}" >
                    <StackPanel x:Name="stack">
                        <TextBlock Text="{Binding Text}" FontSize="13.333" TextWrapping="Wrap"  Foreground="#FFC0C7C8"/>
                        <TextBlock Text="{Binding Status_Message}" FontSize="13.333"  TextWrapping="Wrap" Foreground="#FFC0C7C8"/>
                        </StackPanel>
                    </custom:XSButton>
                </Grid>

the DataTrigger for expanding/collapsing

        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">

                <DataTrigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Grid" Storyboard.TargetProperty="Tag" To="1" Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Grid" Storyboard.TargetProperty="Tag" To="0" Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.ExitActions>
            </DataTrigger>

        </DataTemplate.Triggers>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top