WPF中ListView内定义的Border样式意外应用到控件本身如何解决?
问题原因
你遇到的不是WPF的Bug,是对资源作用域和控件模板逻辑的理解偏差:
- 定义在
ListView.Resources中的无x:Key、仅指定TargetType的隐式样式,作用范围包含当前控件本身及其所有逻辑子节点 - ListView的默认控件模板内部自带一个根Border元素,该元素属于ListView的模板子节点,同样会匹配你定义的Border隐式样式,你设置的Height、Width属性会直接作用到这个模板Border上,最终表现为ListView本身的尺寸被修改
- Background属性没有影响ListView外观的原因是:ListView模板内部的Border的Background默认绑定了ListView本身的Background属性,本地绑定的优先级高于样式值,所以样式里的Background不会作用到模板Border,只会应用到你手动添加的、没有本地Background值的子Border上,才出现了两种属性表现不一致的情况
解决方案
方案1:给Border样式指定x:Key手动引用(最稳妥)
给自定义Border样式添加唯一标识,仅手动应用到你需要的Border元素上,不会影响ListView内部模板的控件:
<ListView HorizontalAlignment="Right" Margin="20"> <ListView.Resources> <Style x:Key="CustomBorderStyle" TargetType="Border"> <Setter Property="Height" Value="20"/> <Setter Property="Width" Value="150"/> <Setter Property="Background" Value="Blue"/> </Style> </ListView.Resources> <Border Style="{StaticResource CustomBorderStyle}"/> <Border Style="{StaticResource CustomBorderStyle}"/> </ListView>
方案2:替换为更合适的布局容器
如果你不需要ListView的列表选择、虚拟化等功能,只是要垂直排列两个Border,直接用StackPanel更简单,也不会有内部模板控件匹配样式的问题:
<StackPanel HorizontalAlignment="Right" Margin="20"> <StackPanel.Resources> <Style TargetType="Border"> <Setter Property="Height" Value="20"/> <Setter Property="Width" Value="150"/> <Setter Property="Background" Value="Blue"/> <Setter Property="Margin" Value="0 0 0 5"/> </Style> </StackPanel.Resources> <Border/> <Border/> </StackPanel>
方案3:针对列表项场景的规范写法
如果你确实需要用ListView做列表展示,建议通过ItemTemplate定义列表项的布局,符合WPF的MVVM设计规范:
<ListView HorizontalAlignment="Right" Margin="20" ItemsSource="{Binding YourItemList}"> <ListView.ItemTemplate> <DataTemplate> <Border Height="20" Width="150" Background="Blue"/> </DataTemplate> </ListView.ItemTemplate> </ListView>
内容的提问来源于stack exchange,提问作者Nigel
相关产品推荐
相关产品推荐

