Reputation: 1425
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.
<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:
Upvotes: 9
Views: 9259
Reputation: 827
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.
Upvotes: 23
Reputation: 102793
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.)
You can calculate the length of a string using the FormattedText
class. 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:
<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.)
Upvotes: 1
Reputation: 5366
You can add HorizontalContentAlignment=Stretch and Add UniformGrid in itemsPanel.
<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>
Upvotes: 2
Reputation: 7467
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 :
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.
Some more info on how to create a custom panel : http://www.wpftutorial.net/CustomLayoutPanel.html
Upvotes: 4