WPF中如何让TextBox内容像Excel单元格那样覆盖其他控件
WPF实现类似Excel的TextBox单元格溢出显示效果
问题场景
使用ItemsControl承载横向排列的TextBox作为单元格,需要实现:当单元格内文本宽度超过自身宽度时,文本可以溢出覆盖在相邻单元格上方,默认布局下超出的内容会被容器裁剪无法显示。
原有实现的XAML代码:
<ItemsControl ItemsSource="{Binding Path=MyCollection}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" Width="100"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <TextBox Text="{Binding}" TextWrapping="WrapWithOverflow"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
实现步骤
默认布局下内容被裁剪有两个核心原因:一是各级布局容器默认开启了边界裁剪,二是TextBox本身默认会裁剪超出自身边界的内容,另外原有代码设置的TextWrapping="WrapWithOverflow"会触发文本折行,不符合横向溢出的需求,按以下步骤修改即可:
- 关闭所有层级容器的边界裁剪:将
ItemsControl、作为项面板的StackPanel、每个项对应的ContentPresenter容器的ClipToBounds属性全部设为False,允许内容超出自身布局槽显示。 - 调整TextBox基础属性:将
TextWrapping改为NoWrap关闭文本折行,给TextBox设置固定单元格宽度,同时将TextBox自身的ClipToBounds设为False,取消文本框自身的内容裁剪。 - 增加Z序控制逻辑:给
TextBox添加触发器,当文本框获得焦点、鼠标悬停时提升Panel.ZIndex值,保证溢出的内容不会被相邻单元格遮挡,和Excel的交互逻辑一致。
完整修改后代码
<ItemsControl ItemsSource="{Binding Path=MyCollection}" ClipToBounds="False"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" Width="100" ClipToBounds="False"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style TargetType="ContentPresenter"> <Setter Property="ClipToBounds" Value="False"/> </Style> </ItemsControl.ItemContainerStyle> <ItemsControl.ItemTemplate> <DataTemplate> <TextBox Text="{Binding}" Width="25" Margin="0" TextWrapping="NoWrap" ClipToBounds="False"> <TextBox.Style> <Style TargetType="TextBox"> <Setter Property="Panel.ZIndex" Value="0"/> <Style.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="Panel.ZIndex" Value="99"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Panel.ZIndex" Value="99"/> </Trigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
扩展说明:如果需要完全对齐Excel的逻辑——即相邻单元格为空时才允许溢出显示、相邻单元格有内容时自动截断文本,只需额外增加绑定逻辑,判断相邻项的内容是否为空,动态切换当前
TextBox的ClipToBounds属性即可。
内容的提问来源于stack exchange,提问作者ahmed shawkey
相关产品推荐
相关产品推荐

