c# - WPF ListView 通过标题模板与扩展器分组?

标签 c# .net wpf listview expander

我能找到的所有将 Expander 实现为 WPF 中 ListView 组的示例都是通过为GroupStyle.ContainerStyle 属性中的 GroupItem

可以找到这样的示例 here ,并且它按预期工作。

但是它确实有一个缺陷,如果您添加额外的GroupDescription(用于多级分组),则第二级和后续级别不会像仅覆盖标题时那样缩进模板而不是容器样式。

我偶然注意到,GroupItem 代码似乎确实支持在其模板中定位 Expander 控件(如果这是递归搜索)建议可以用更简单的样式替换上面的组样式,如下所示:

<GroupStyle>
    <GroupStyle.HeaderTemplate>
        <DataTemplate DataType="GroupItem">
            <Expander IsExpanded="True">
                <Expander.Header>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}"
                                   FontWeight="Bold" Foreground="Gray"
                                   FontSize="22" VerticalAlignment="Bottom" />
                        <TextBlock Text="{Binding ItemCount}" FontSize="22"
                                   Foreground="Green" FontWeight="Bold"
                                   FontStyle="Italic" Margin="10,0,0,0"
                                   VerticalAlignment="Bottom" />
                        <TextBlock Text=" item(s)" FontSize="22"
                                   Foreground="Silver" FontStyle="Italic"
                                   VerticalAlignment="Bottom" />
                    </StackPanel>
                </Expander.Header>
                <ItemsPresenter />
            </Expander>
        </DataTemplate>
    </GroupStyle.HeaderTemplate>
</GroupStyle>

即。相同的核心 Expander,但在 HeaderTemplate 中表达,而不是在 ContainerStyle 中。

几乎可以工作——视觉上它看起来是正确的,甚至具有预期的多个级别的缩进。但切换 Expander 实际上并不会显示或隐藏组中的项目,因此显然视觉层次结构是错误的。

我有几个问题:

  1. 有办法让这个工作像这样吗?
  2. 如果不是,那么 GroupItem 实际使用 Expander 检测做什么?
  3. 坚持原来的ContainerStyle,有没有办法保持自然缩进?

最佳答案

首先,如果您将 Expander 放在 header 模板中,GroupItem 将无法识别它(如果您检查 source code (特别是 this 帮助器)方法)您就会明白为什么 - 它会查找后代 Expander,但将 TemplatedParent 设置为有问题的 GroupItem,而如果 Expander 是 header 模板的一部分,其 TemplatedParent 将是 ContentPresenter1

其次,即使它被识别,GroupItem 也不会真正处理组项目的可见性 - 这是由 Expander 模板完成的(当它展开其 >Content 可见,否则不可见)。 GroupItem 仅在启用 UI 虚拟化时处理一些边缘情况,并回收它来表示另一个项目(基本上它归结为使所有者 ItemsControl 上的度量无效)。

最后,正确的方法是将 Expander 放入 GroupItem 模板中(通过 GroupStyle.ContainerStyle)。如果您盲目遵循引用的示例,那么是的,不会有任何缩进。但是,您需要做的就是在 ItemsPresenter 上设置所需的边距,例如:

<GroupStyle>
    <GroupStyle.ContainerStyle>
        <Style TargetType="{x:Type GroupItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type GroupItem}">
                        <Expander Header="{Binding Name}">
                            <ItemsPresenter Margin="20,0,0,0" />
                        </Expander>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </GroupStyle.ContainerStyle>
</GroupStyle>

瞧! - 你已经有了一个很好的(并且“递归”)缩进。


1 假设您不覆盖默认 GroupItem 模板

关于c# - WPF ListView 通过标题模板与扩展器分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48456637/

相关文章:

WPF/XAML - 文本可以自动调整大小吗?

c# - 如何使用括号动态创建 "System.Linq.Expression"表达式

.net - 带有 .Net 后端的 Azure 移动服务的新遗迹

c# - 如何在自定义用户控件(.Net 4、Winforms)上使用项目集合编辑器?

c# - WPF:绑定(bind)到具有自定义行为的类的属性

.net - 如何生成一个与主机名不同的.EXE?

c# - 虚拟方法比调用非虚拟方法慢

c# - 在 LINQ 中将 2 个 xml 合并为一个新 XML 的有效方法

c# - DataView.Sort是性能瓶颈

具有类自动生成 : Subsonic, CaSTLe AR 的 .NET ORM 解决方案,...?