如何访问WPF GroupItem模板中的元素

时间:2018-08-29 14:24:34

标签: c# wpf controltemplate expander

我有一个ListView,里面装满了一些物品。这些项目具有两个属性ItemNameItemGroup,我想按它们的第二个属性进行分组。所以我写了这样的东西:

<Grid>
    <Grid.Resources>
        <Style x:Key="groupStyle" TargetType="{x:Type GroupItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Expander IsExpanded="False" Header="{Binding Name}">
                            <ItemsPresenter />
                        </Expander>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <ListView x:Name="lv">
        <ListView.View>
            <GridView>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding ItemName}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
        <ListView.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource groupStyle}"/>
        </ListView.GroupStyle>
    </ListView>
</Grid>

以及后面的代码

// here, list is the collection of items with mentioned properties.
lv.ItemsSource = list;
var view = (CollectionView) CollectionViewSource.GetDefaultView(lv.ItemsSource);
if (view.GroupDescriptions != null)
{
    view.GroupDescriptions.Clear();
    view.GroupDescriptions.Add(new PropertyGroupDescription("ItemGroup"));
}

现在一切正常。但是问题是,有时我想在代码后面扩展所有Expander,而我却找不到访问它们并将IsExpanded属性设置为true的方法。我该怎么办?

编辑:这是我用来查找扩展器的方法,例如FindChildren<Expander>(lv)但它总是返回一个空集合

public static IEnumerable<T> FindChildren<T>(DependencyObject ui) where T : DependencyObject
{
    if (ui == null) yield break;
    int childcount = ui is Visual ? VisualTreeHelper.GetChildrenCount(ui) : 0;

    if (childcount == 0)
    {
        var children = LogicalTreeHelper.GetChildren(ui).OfType<DependencyObject>();

        foreach (T descendant in children.SelectMany(FindChildren<T>))
            yield return descendant;
    }
    for (int n = 0; n < childcount; n++)
    {
        var child = VisualTreeHelper.GetChild(ui, n);
        if (child is T)
        {
            yield return (T) child;
            continue;
        }
        foreach (T descendant in FindChildren<T>(child))
            yield return descendant;
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用递归方法和Expander类在视觉树中找到VisualTreeHelper元素:

private void ExpandButton_Click(object sender, RoutedEventArgs e)
{
    foreach (Expander gi in FindVisualChildren<Expander>(lv))
    {
        gi.IsExpanded = true;
    }
}

private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
}

编辑:如果要在设置ItemsSource的{​​{1}}属性后立即执行此操作,则需要等待直到容器创建完成。处理ListView事件:

Loaded

答案 1 :(得分:0)

很奇怪,@ mm8发布的答案无效,我也不知道为什么。但是无论如何我还是设法解决了。关键是将扩展器的IsExpanded属性绑定到ListView的未使用属性,例如其标签:

<ControlTemplate>
    <Expander Header="{Binding Name}">
        <Expander.IsExpanded>
            <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListView}" Path="Tag" />
        </Expander.IsExpanded>
        <ItemsPresenter />
    </Expander>
</ControlTemplate>

然后您可以通过在代码中设置IsExpandedlv.Tag = true;来控制所有lv.Tag = false;的属性。