是否可以通过编程方式滚动WPF ListView,以便在其顶部放置所需的分组标题?

时间:2019-07-20 00:07:00

标签: c# wpf xaml wpf-listview

给定ListView绑定到使用PropertyGroupDescription分组的项目,是否可以通过编程方式滚动以便将组放置在列表的顶部?我知道我可以滚动到组中的第一项,因为该项属于ListView绑定到的集合。但是,我找不到任何资源来描述如何滚动到组头(以GroupStyle样式)。

要给出所需功能的示例,我们来看一下 Visual Studio Code 中的设置页面。该页面由一个面板组成,该面板允许用户滚动应用程序的所有设置(在各自的组下组织)以及左侧的树状结构,以便更快地导航至主面板中的特定组。在所附的屏幕快照中,我单击了左侧树中的 Formatting (格式设置)选项,主面板自动滚动,因此相应的组标题位于主面板的顶部。

如何在WPF中重新创建它(如果可能的话)?使用另一个WPF控件可以模仿 Visual Studio Code 中主设置面板的“无限”滚动吗?

enter image description here

1 个答案:

答案 0 :(得分:0)

当然可以。实际设置结构的设计可能有几种变化。它可以是一棵树,其中每个类别标题节点都有自己的子节点,这些子节点代表一个类别的设置;或者是一个平面列表结构,其中类别标题和设置都是同级的。为了简化示例,我选择第二个选项:平面数据结构。

左侧的树(TOC)具有根节点(例如“ TextEditor”部分)。每个部分都包含设置类别(例如“格式设置”)

设置:

  • 您需要两个ItemsControl元素:
      左侧导航窗格为
    • 一个TreeView,分为两个级别
      • 具有节的父节点(例如“文本编辑器”)
      • 以及该部分的设置类别标题子节点(例如'Font','Formatting')
    • 一个ListView用于实际设置及其类别标题。
  • 然后设计数据类型以表示设置,设置标头和节根节点
    • 让它们全部实现具有共享属性(例如标头)的公用IData
    • 让设置标头数据类型实现附加 IHeaderData
    • 让设置数据类型实现额外的ISettingData
    • TreeView的父节节点数据类型(根节点)实现一个附加的ISectionData,其子类型为IHeaderData
  • 创建商品来源集合
    • TreeView(仅包含类别)的每个父节节点,一个SectionCollection类型的ISectionData
    • 每个类别一个,类型为CategoryCollection的{​​{1}}
    • 一个用于设置数据和共享类别(标头数据)的类型,一个IHeaderData类型的SettingCollection
  • 逐节填充已排序的源集合
    • 将类型IData的部分数据实例添加到ISectionData的源集合SectionCollection
    • 将类型为TreeView的共享类别数据标头实例添加到两个源集合IHeaderDataCategoryCollection
    • 仅将SettingCollection类型的设置实例(类别的每个设置一个)添加到ISettingData
    • 针对当前部分的所有类别重复最后两个步骤
    • SettingCollection分配给CategoryCollection根节点的子集合
    • 重复所有部分的步骤(及其类别和相应的设置)
  • ISectionData绑定到SectionCollection
  • TreeView绑定到SettingsCollection
  • LIstView类型为根的HierarchicalDataTemplate数据创建TreeView
  • ISectionData创建两个DataTemplate
    • 一个针对ListView的人
    • 一个针对IHeaderData的人

逻辑:

  • 当选择ISettingData的{​​{1}}项目时,
    • 使用IHeaderDataTreeView中获取相应数据项的项目容器
    • 将容器滚动到视图ListView(以实现视图之外的虚拟化项目)
    • 将容器滚动到视图顶部

由于var container = ItemsContainerGenerator.GetContainerFromItem(selectedTreeViewCategoryItem)container.BringIntoView()共享相同的类别标题数据(TreeView),因此所选项目易于跟踪和查找。您无需搜索设置组。您可以使用参考直接跳到该组。 这意味着数据的结构是解决方案的关键。

编辑以解决ListView

的使用

我假设在IHeaderData内部定义了一个PropertyGroupDescription。设置数据项还具有属性CollectionViewSource

ResourceDictionary

找到该部分并将其显示:

SettingsSectionName

您可以将此方法移动到<ResourceDictionary> <CollectionViewSource x:Key="CollectionViewSource" Source="{Binding Settings}"> <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="SettingsSectionName"/> </CollectionViewSource.GroupDescriptions> </CollectionViewSource> </ResourceDictionary> <ListView x:Name="ListView" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}"> <ListView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock FontWeight="Bold" FontSize="14" Text="{Binding Name}" /> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> </ListView> 派生类型中。然后将private void ScrollToSection(string sectionName) { CollectionViewSource viewSource = FindResource("CollectionViewSource") as CollectionViewSource; CollectionViewGroup selectedGroupItemData = viewSource .View .Groups .OfType<CollectionViewGroup>() .FirstOrDefault(group => group.Name.Equals(sectionName)); GroupItem selectedroupItemContainer = this.ListView.ItemContainerGenerator.ContainerFromItem(selectedGroupItemData) as GroupItem; selectedGroupItemContainer.BringIntoView(); } 添加到处理路由命令的新自定义ListView中,例如CommandBindings。将ListView模板化为ScrollToSectionRoutedCommand,然后让他们发出命令,将节名称作为TreeViewItems传递给自定义Button