WPF - Group分组对ListBox等列表样式的约束
原文:WPF - Group分组对ListBox等列表样式的约束
在做WPF主题支持时,出现一个分组引起的莫名错误,可是折腾了我一番。在没有使用样式时,列表分组很正常,使用了别人写的ListBox列表样式后,发现GroupItem分组区没有内容,是空的,本篇把这一问题的解决过程给大家说一下,做主题时可以注意分组对列表样式的限制了。
ListBox增加分组
WPF为ItemsControl提供很多的样式扩展,要想实现列表分组也很简单,只需要做以下几步就可以了:
- 给列表控件增加分组样式

代码
<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="" SnapsToDevicePixels="true" X1="" X2="" Stretch="Fill" StrokeThickness=""/>
</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); 给数据增加分组

代码
<UserControl.Resources>
<CollectionViewSource Source="{x:Static oea:ApplicationModel.DefaultBusinessObjectInfos}" x:Key="cvs">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Catalog" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
使用ListBox样式后
用了别人的一个ListBox样式文件,样式如下:

代码
<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="" />
<GradientStop Color="{DynamicResource SecondaryColor}" Offset="" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="" />
<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="" CornerRadius="4,4,4,4">
<Grid>
<ScrollViewer Padding="{TemplateBinding Padding}" Focusable="false" x:Name="scrollViewer">
<StackPanel Margin="" 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>
用完之后运行发现界面不对,点击分组标题后列表内容没有显示???

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

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

解决问题
原因知道了,解决问题也就非常简单了,修改样式表,主要就是把
<StackPanel Margin="2" IsItemsHost="true"/>
该为
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
修改后再次运行,界面正确,如下:

更多内容:
开源信息系统开发平台之OpenExpressApp框架.pdf
欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]
WPF - Group分组对ListBox等列表样式的约束的更多相关文章
- C# WPF DataGrid 分组(Group)
原文:C# WPF DataGrid 分组(Group) 效果如图,每个列的名字可以自定义.我随便用了”File”和”Attachment Name”. 在Window的Resources里面设置S ...
- WPF中修改ListBox项的样式病修改选中项的背景颜色
最终效果: 1 <ListBox Name="cmb"> 2 <!--修改颜色--> 3 <ListBox.Resources> 4 <! ...
- signalr中Group 分组群发消息的简单使用
前一段时间写了几篇关于signalr的文章 1.MVC中使用signalR入门教程 2.mvc中signalr实现一对一的聊天 3.Xamarin android中使用signalr实现即时通讯 在平 ...
- WPF 4 DataGrid 控件(自定义样式篇)
原文:WPF 4 DataGrid 控件(自定义样式篇) 在<WPF 4 DataGrid 控件(基本功能篇)>中我们已经学习了DataGrid 的基本功能及使用方法.本篇将继续 ...
- 浅析mongodb中group分组
这篇文章主要介绍了浅析mongodb中group分组的实现方法及示例,非常的简单实用,有需要的小伙伴可以参考下. group做的聚合有些复杂.先选定分组所依据的键,此后MongoDB就会将集合依据选定 ...
- CSS3初学篇章_5(背景样式/列表样式/过渡动画)
背景样式 1.背景颜色语法:background-color : transparent | color body { background-color:#CCCCCC;} 2.渐变色彩语法:back ...
- WPF后台设置xaml控件的样式System.Windows.Style
WPF后台设置xaml控件的样式System.Windows.Style 摘-自 :感谢 作者: IT小兵 http://3w.suchso.com/projecteac-tual/wpf-zhi ...
- WPF如何用TreeView制作好友列表、播放列表
WPF如何用TreeView制作好友列表.播放列表 前言 TreeView这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表).音乐播放器(播放列表).类库展示器(树形类结构)等都用的是T ...
- SharePoint 2010 修改默认列表样式
SharePoint 2010 修改默认列表样式 :可以通过修改 下面两个全局配置进行修改.(未完..更新中...) C:\Program Files\Common Files\Microsoft ...
随机推荐
- Qt5 编译 & 打包依赖dll发布
十年前学C++的时候,无聊到把windows 文件夹下几乎所有的*.dll 都看过一遍.偶尔在程序运行时看到缺少 *.dll 的提示,都会直接找出来解决. 随着“开发平台”和“编译器”版本的逐年升级, ...
- hibernate级联保存问题
异常:org.hibernate.TransientObjectException: object references an unsaved transient instance 解决方法: XML ...
- 检测dll是32/64位?(直接读dll文件包含的某几个字节进行判断)
检查dll是32位还是64位? #include "stdafx.h" #include <Windows.h> int _tmain(int argc, _TCHAR ...
- <Linux> Xen虚拟机下挂载
//创建源vdisk挂载目录: mkdir vd1 //创建目标vdisk挂载目录: mkdir vd2 //只需第一次执行: iscsiadm -m discovery --type sendta ...
- springmvc中controller内方法跳转forward?redirect?
使用springmvc的controller的时候,碰到controller内方法的跳转的问题,记录下问题以及自己测试的过程. 场景: 业务执行更新操作之后返回列表页面,列表页面需默认展示查询的列表数 ...
- thinkphp5开发规范(加强复习之前的)
thinkphp5开发规范(加强复习之前的) 一.总结 一句话总结:和类相关的采用驼峰命名法:变量,函数,类,方法,属性采用驼峰命名发:数据库及文件及配置参数是小写字母加下划:常量大写加下划线 1.T ...
- Android ReentrantLock
synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候. 1.某个线程在等待一 ...
- log4j配置参考手册:log4j.properties和log4j.xml两种格式
log4j是Java Web开发中,最常用的日志组件之一.网上关于log4j的配置满天飞,我主要是从网上学习的配置.之前的很多年,主要使用log4j.properties这种格式.后来,项目中boss ...
- js进阶 9-8 html标签如何实现禁止复制和粘贴
js进阶 9-8 html标签如何实现禁止复制和粘贴 一.总结 一句话总结: 1.在oncopy方法中return false即可阻止在控件中复制内容 2.在onpaste方法中return fal ...
- [Erlang 0057] Erlang 排错利器: Erlang Crash Dump Viewer
http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html Erlang Crash Dump Viewer真的是排错的天兵神器,还记得我 ...