WPF: synchronizing the width of all elements in an ItemsControl

Is it possible to adjust the width of all text blocks in a WrapPanel to the size of the largest text block in a WrapPanel? The end result should be that the width of the control containing "Some data" is the same width as the control containing "Even more data than before." As a starting point, I attached my original code. I used strings as an example, but the collection and template data can be anything, so I cannot 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 the image of the desired result:

Desired output

+5
source share
4 answers

Use the overall mesh size:

 <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 have the same width as the size group. As they automatically size, they will also scale to the largest instance of any mesh content.

+10
source

You need to create your own version of the shell, which is obtained from the cover to achieve the desired. Typically for a custom panel, you should override the following 2 methods:

  • MeasureOverride
  • Arrangeoververride

In your case, you will need a measueoverride where you will iterate over the elements and find out which one is the largest, and then use the same size for all the elements in ordering mode.

For more information about how to create a custom panel: http://www.wpftutorial.net/CustomLayoutPanel.html

+4
source

You can add HorizontalContentAlignment = Stretch and Add UniformGrid to 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> 
+2
source

This is an alternative to the Philip Stuyck panel offer, which you may find simpler for your specific scenario. (In truth, this is a hack.)

You can calculate the length of a string using the FormattedText class. This way you can iterate over the strings and calculate the maximum length (this also assumes that you know the font family and size). Then just snap the width of your text blocks to the maximum width. I would save the width value in one property at the parent level, and then using the RelativeSource binding:

 <TextBlock Text="{Binding}" Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=MaximumWidth}}" /> 

(One of the drawbacks of this approach is that if the collection of elements changes, you will have to recalculate MaximumWidth.)

+1
source

Source: https://habr.com/ru/post/1215173/


All Articles