WPF:同步 ItemsControl 中所有项目的宽度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28995443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF: Synchronize width of all items in ItemsControl
提问by mortalapeman
Is it possible to adjust the width of all TextBlocks in the WrapPanel to the size of the largest TextBlock within the WrapPanel? The end result should be that the width of the control containing "Some data" has the same width as the control containing "Even more data than before." I have attached to my initial code as a starting point. I have used strings as an example, but the collection data and template could be anything, so I can't rely on the length of the string.
是否可以将 WrapPanel 中所有 TextBlock 的宽度调整为 WrapPanel 内最大 TextBlock 的大小?最终结果应该是包含“一些数据”的控件的宽度与包含“比以前更多的数据”的控件的宽度相同。我附上了我的初始代码作为起点。我以字符串为例,但集合数据和模板可以是任何东西,所以我不能依赖字符串的长度。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Collections:ArrayList x:Key="data">
<System:String>Some data</System:String>
<System:String>Some more data</System:String>
<System:String>Even more data than before</System:String>
</Collections:ArrayList>
</Window.Resources>
<ItemsControl ItemsSource="{StaticResource data}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding}"></TextBlock>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
And an image of the desired output:
以及所需输出的图像:


回答by Toby Crawford
Use a shared size grid:
使用共享大小网格:
<ItemsControl ItemsSource="{StaticResource data}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="ColumnSize" />
</Grid.ColumnDefinitions>
<Border Margin="5" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding}"></TextBlock>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
All columns are guaranteed to be the same width as they share a size group. As they are sized auto, they will also size to the largest instance of any of the grid's content.
所有列都保证具有相同的宽度,因为它们共享一个大小组。由于它们的大小是自动的,因此它们的大小也将调整为任何网格内容的最大实例。
回答by Philip Stuyck
You have to create your own custom version of a wrappanel that is derived from wrappanel to achieve what you want. Normally for a custom panel you have to override following 2 methods :
您必须创建自己的自定义版本的 wrappanel,它派生自 wrappanel 以实现您想要的。通常对于自定义面板,您必须覆盖以下两种方法:
- MeasureOverride
- ArrangeOverride
- 测量覆盖
- 安排覆盖
In your case you need measueoverride where you will iterate over the elements and find out which one is the biggest and then use that same size for all elements in arrangeoverride.
在您的情况下,您需要 measueoverride,您将在其中迭代元素并找出最大的元素,然后对排列覆盖中的所有元素使用相同的大小。
Some more info on how to create a custom panel : http://www.wpftutorial.net/CustomLayoutPanel.html
关于如何创建自定义面板的更多信息:http: //www.wpftutorial.net/CustomLayoutPanel.html
回答by Ayyappan Subramanian
You can add HorizontalContentAlignment=Stretch and Add UniformGrid in itemsPanel.
您可以在 itemsPanel 中添加 HorizontalContentAlignment=Stretch 和 Add UniformGrid。
<Window.Resources>
<Collections:ArrayList x:Key="data">
<System:String>Some data</System:String>
<System:String>Some more data</System:String>
<System:String>Even more data than before</System:String>
</Collections:ArrayList>
</Window.Resources>
<ListBox ItemsSource="{StaticResource data}" HorizontalContentAlignment="Stretch">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid IsItemsHost="True"></UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderThickness="1" BorderBrush="Black" >
<TextBlock Text="{Binding}" Width="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=Width}"></TextBlock>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
回答by McGarnagle
This is an alternative to Philip Stuyck's custom panel suggestion that you may find more straightforward for your particular scenario. (It is a bit of a hack admittedly.)
这是 Philip Stuyck 的自定义面板建议的替代方案,您可能会发现对于您的特定场景更直接。(诚然,这有点像黑客。)
You can calculate the length of a string using the FormattedTextclass. So you could iterate over your strings and calculate the maximum length (this also assumes that you know the font family and size). Then just bind the width of your text blocks to the maximum width. I would store the width value in a single property at the parent level, then using a RelativeSource binding:
您可以使用FormattedText该类计算字符串的长度。所以你可以迭代你的字符串并计算最大长度(这也假设你知道字体系列和大小)。然后只需将文本块的宽度绑定到最大宽度。我会将宽度值存储在父级别的单个属性中,然后使用 RelativeSource 绑定:
<TextBlock Text="{Binding}"
Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},
Path=MaximumWidth}}"
/>
(One drawback of this approach is that if the items collection changes, you'll have to recalculate MaximumWidth.)
(这种方法的一个缺点是,如果项目集合发生变化,您将不得不重新计算 MaximumWidth。)

