WPF ComboBox文本过长时尾部显示省略号设置无效如何解决
问题原因
你写的样式不生效,本质是WPF的资源查找和模板渲染规则导致的:
- 你在
ComboBox的Style.Resources中定义的无Key隐式TextBlock样式,只能作用于ComboBox逻辑树里显式声明的TextBlock元素。 - ComboBox默认模板中,显示选中项的区域、下拉列表项的内容区域都用
ContentPresenter承载,当内容是纯字符串时,ContentPresenter会在自己的可视化子树内部自动生成TextBlock渲染文本,这个自动生成的TextBlock不会向上查找父级ComboBox资源里的隐式样式,自然不会命中你写的TextTrimming设置。
可行解决方案
最稳妥、不需要改动后台代码的方案,是直接给模板内的ContentPresenter设置文本裁剪附加属性——TextBlock的附加属性可以直接作用于ContentPresenter自动生成的内部TextBlock,不需要额外写隐式样式。
你可以直接替换App.xaml里原来的ComboBox样式为如下版本:
<!-- ComboBox全局样式 --> <Style TargetType="{x:Type ComboBox}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Grid> <ToggleButton x:Name="ToggleButton" Focusable="false" ClickMode="Press" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/> <!-- 选中项显示区域,关键是添加TextBlock.TextTrimming附加属性设置 --> <ContentPresenter x:Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Margin="3,3,23,3" VerticalAlignment="Center" HorizontalAlignment="Left" TextBlock.TextTrimming="CharacterEllipsis" TextBlock.TextWrapping="NoWrap"/> <Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide"> <Grid x:Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}"> <Border x:Name="DropDownBorder" Background="White" BorderBrush="#FF888888" BorderThickness="1"/> <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True"> <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/> </ScrollViewer> </Grid> </Popup> </Grid> <!-- 模板触发器、视觉状态可以直接保留系统默认ComboBox的默认配置,不需要修改 --> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- 下拉项样式,保证下拉列表长文本也显示省略号 --> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBoxItem}"> <Border x:Name="Bd" Padding="2,1,2,1" SnapsToDevicePixels="True"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" TextBlock.TextTrimming="CharacterEllipsis" TextBlock.TextWrapping="NoWrap"/> </Border> <!-- 模板触发器、视觉状态保留系统默认配置即可 --> </ControlTemplate> </Setter.Value> </Setter> </Style>
如果不想重写整个控件模板,也可以用轻量方案:显式给ComboBox指定ItemTemplate,强制用自定义的TextBlock渲染每个项,同时给ComboBox设置SelectionBoxItemTemplate来处理选中项的文本裁剪,这种方案不需要修改你现有的后台数据加载逻辑。
注意:如果使用轻量模板方案,要确保ComboBox的
IsEditable属性为False(默认值就是False),可编辑模式下的文本框需要单独设置裁剪属性。
内容的提问来源于stack exchange,提问作者bbz
相关产品推荐
相关产品推荐

