WPF - Group分组对ListBox等列表样式的约束

简介: 原文:WPF - Group分组对ListBox等列表样式的约束  在做WPF主题支持时,出现一个分组引起的莫名错误,可是折腾了我一番。在没有使用样式时,列表分组很正常,使用了别人写的ListBox列表样式后,发现GroupItem分组区没有内容,是空的,本篇把这一问题的解决过程给大家说一下,做主题时可以注意分组对列表样式的限制了。
原文: WPF - Group分组对ListBox等列表样式的约束

  在做WPF主题支持时,出现一个分组引起的莫名错误,可是折腾了我一番。在没有使用样式时,列表分组很正常,使用了别人写的ListBox列表样式后,发现GroupItem分组区没有内容,是空的,本篇把这一问题的解决过程给大家说一下,做主题时可以注意分组对列表样式的限制了。

ListBox增加分组img_f3abdad0980e98855d4c7f97968ac7e7.jpe

  WPF为ItemsControl提供很多的样式扩展,要想实现列表分组也很简单,只需要做以下几步就可以了:

  1. 给列表控件增加分组样式
    img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
     
        
    < Style x:Key = " GroupContainerStyle " TargetType = " {x:Type GroupItem} " >
    < Setter Property = " Template " >
    < Setter.Value >
    < ControlTemplate TargetType = " {x:Type GroupItem} " >
    < Expander IsExpanded = " True " >
    < Expander.Header >
    < Grid >
    < Grid.ColumnDefinitions >
    < ColumnDefinition Width = " Auto " />
    < ColumnDefinition />
    </ Grid.ColumnDefinitions >
    < Grid.RowDefinitions >
    < RowDefinition />
    </ Grid.RowDefinitions >
    < StackPanel Orientation = " Horizontal " Margin = " 0,0,10,0 " >
    < TextBlock Text = " {Binding Path=Name} " FontWeight = " Bold " />
    < TextBlock FontWeight = " Bold " Text = " {Binding Path=ItemCount, StringFormat=(共{0}条)} " />
    </ StackPanel >
    < Line Grid.Column = " 1 " SnapsToDevicePixels = " true " X1 = " 0 " X2 = " 1 " Stretch = " Fill " StrokeThickness = " 1 " />
    </ Grid >
    </ Expander.Header >
    < ItemsPresenter />
    </ Expander >
    </ ControlTemplate >
    </ Setter.Value >
    </ Setter >
    </ Style >

     
       
    GroupStyle gs = new GroupStyle();
    gs.ContainerStyle
    = Application.Current.TryFindResource( " GroupContainerStyle " ) as Style;
    lbModule.GroupStyle.Add(gs);
  2. 给数据增加分组

    img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
     
        
    < UserControl.Resources >
    < CollectionViewSource Source = " {x:Static oea:ApplicationModel.DefaultBusinessObjectInfos} " x:Key = " cvs " >
    < CollectionViewSource.GroupDescriptions >
    < PropertyGroupDescription PropertyName = " Catalog " />
    </ CollectionViewSource.GroupDescriptions >
    </ CollectionViewSource >
    </ UserControl.Resources >

使用ListBox样式后

  用了别人的一个ListBox样式文件,样式如下:

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
 
  
< Style TargetType = " {x:Type ListBox} " >
< Setter Property = " Background " Value = " {DynamicResource {x:Static SystemColors.WindowBrushKey}} " />
< Setter Property = " BorderBrush " >
< Setter.Value >
< LinearGradientBrush EndPoint = " 0.5,1 " StartPoint = " 0.5,0 " >
< GradientStop Color = " {DynamicResource PrimaryColor} " Offset = " 0 " />
< GradientStop Color = " {DynamicResource SecondaryColor} " Offset = " 1 " />
</ LinearGradientBrush >
</ Setter.Value >
</ Setter >
< Setter Property = " BorderThickness " Value = " 1 " />
< Setter Property = " Foreground " Value = " {DynamicResource {x:Static SystemColors.ControlTextBrushKey}} " />
< Setter Property = " ScrollViewer.HorizontalScrollBarVisibility " Value = " Auto " />
< Setter Property = " ScrollViewer.VerticalScrollBarVisibility " Value = " Auto " />
< Setter Property = " ScrollViewer.CanContentScroll " Value = " true " />
< Setter Property = " VerticalContentAlignment " Value = " Center " />
< Setter Property = " Template " >
< Setter.Value >
< ControlTemplate TargetType = " {x:Type ListBox} " >
< Border x:Name = " Bd " SnapsToDevicePixels = " true " Background = " {TemplateBinding Background} " BorderBrush = " {TemplateBinding BorderBrush} " BorderThickness = " {TemplateBinding BorderThickness} " Padding = " 1 " CornerRadius = " 4,4,4,4 " >
< Grid >
< ScrollViewer Padding = " {TemplateBinding Padding} " Focusable = " false " x:Name = " scrollViewer " >
< StackPanel Margin = " 2 " IsItemsHost = " true " />

<!--< ItemsPresenter SnapsToDevicePixels = " {TemplateBinding SnapsToDevicePixels} " />-->
</ ScrollViewer >
< Border CornerRadius = " 4,4,4,4 " Visibility = " Collapsed " x:Name = " border " Margin = " -2,-2,-2,-2 " >
< Border.Background >
< SolidColorBrush Color = " {DynamicResource DisabledColor} " />
</ Border.Background >
</ Border >
</ Grid >
</ Border >
< ControlTemplate.Triggers >
< Trigger Property = " IsEnabled " Value = " false " >
< Setter Property = " Visibility " TargetName = " border " Value = " Visible " />
</ Trigger >
< Trigger Property = " IsGrouping " Value = " true " >
< Setter Property = " ScrollViewer.CanContentScroll " Value = " false " />
</ Trigger >
</ ControlTemplate.Triggers >
</ ControlTemplate >
</ Setter.Value >
</ Setter >
</ Style >

用完之后运行发现界面不对,点击分组标题后列表内容没有显示???

  img_206a3f17da370d9166a3136b464952bc.jpe

查找原因

  自己想了一下,原因不明,无奈自己对WPF实现只了解一点,于是网上搜索ItemsPresenter empty,找到第一条网页ItemsPresenter + ItemsPanelTemplate vs Panel marked with IsItemsHost,进去后发现他提出了一个问题,就是在分组时如何取ItemsPresenter,发现Reflector工具可以看到以下代码:

 
img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
 
  
internal static ItemsPresenter FromGroupItem(GroupItem groupItem)
{
if (groupItem == null )
{
return null ;
}
Visual parent
= VisualTreeHelper.GetParent(groupItem) as Visual;
if (parent == null )
{
return null ;
}
return (VisualTreeHelper.GetParent(parent) as ItemsPresenter);
}

 

这个帖子上面也解释了为什么这么设计,我就不再重复了,原来在分组时对控件样式有要求,那就是控件样式必须存在ItemsPresenter。

确认原因

使用《WPF - Visual调试工具Snoop》工具查看一下,发现GroupItem下的ItemsPresenter是空的

img_b29c09c3115dc87b02face3f7cd412c5.jpe

切换回不使用样式再看看,发现在GroupItem之上有一个ItemsPresenter,而应用上面样式之后就没有了,果然就是样式文件的控件模板缺少ItemsPresenter的原因。

img_a31c342c07c4aa52fda1d55e88969b55.jpe

解决问题

原因知道了,解决问题也就非常简单了,修改样式表,主要就是把

<StackPanel Margin="2" IsItemsHost="true"/>

该为

<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

修改后再次运行,界面正确,如下:

img_eb0738df7a6242afe34a8ad5208caa2c.jpe

 

更多内容:productView-pdf_46x35.gif 开源信息系统开发平台之OpenExpressApp框架.pdf

 

 

欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]

目录
相关文章
|
12月前
|
缓存 C# 虚拟化
WPF列表性能提高技术
WPF数据绑定系统不仅需要绑定功能,还需要能够处理大量数据而不会降低显示速度和消耗大量内存,WPF提供了相关的控件以提高性能,所有继承自`ItemsControl`的控件都支持该技术。
WPF疑难问题之Treeview中HierarchicalDataTemplate多级样式
WPF疑难问题之Treeview中HierarchicalDataTemplate多级样式
302 0
|
2月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
2月前
|
开发者 C# 存储
WPF开发者必读:资源字典应用秘籍,轻松实现样式与模板共享,让你的WPF应用更上一层楼!
【8月更文挑战第31天】在WPF开发中,资源字典是一种强大的工具,用于共享样式、模板、图像等资源,提高了应用的可维护性和可扩展性。本文介绍了资源字典的基础知识、创建方法及最佳实践,并通过示例展示了如何在项目中有效利用资源字典,实现资源的重用和动态绑定。
44 0
|
2月前
|
开发者 C# 存储
WPF开发者必读:样式与模板的艺术,轻松定制UI外观,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,样式与模板是实现美观界面与一致性的关键工具。样式定义了控件如字体、颜色等属性,而模板则允许自定义控件布局与子控件,两者均可存储于`.xaml`文件中。本文介绍了样式与模板的基础知识,通过示例展示了如何创建并应用它们来改变按钮的外观,从而提升用户体验。
34 0
|
2月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(5) -- 树列表TreeView的使用
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(5) -- 树列表TreeView的使用
|
2月前
|
存储 设计模式 开发框架
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(7) -- 图标列表展示和选择处理
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(7) -- 图标列表展示和选择处理
|
2月前
|
开发框架 前端开发 JavaScript
在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果
在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果
在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果
|
2月前
|
开发框架 .NET C#
WPF/C#:显示分组数据的两种方式
WPF/C#:显示分组数据的两种方式
43 0
|
2月前
|
存储 前端开发 C#
WPF/C#:更改界面的样式
WPF/C#:更改界面的样式
35 0