DCSIMG
WPF Tip: SharedSizeGroup - Pavel's Blog
Sign in | Join | Help

Pavel's Blog

Pavel is a software guy that is interested in almost everything
software related... way too much for too little time

WPF Tip: SharedSizeGroup

Suppose we want to display a set of objects in a ListBox (or other ItemsControl) using a DataTemplate that uses a Grid:

  1. <ListBox HorizontalContentAlignment="Stretch" x:Name="_list" >
  2.     <ListBox.ItemTemplate>
  3.         <DataTemplate>
  4.             <Border Margin="2" BorderBrush="Blue" BorderThickness="2" Padding="2">
  5.                 <Grid>
  6.                     <Grid.ColumnDefinitions>
  7.                         <ColumnDefinition Width="Auto" />
  8.                         <ColumnDefinition />
  9.                     </Grid.ColumnDefinitions>
  10.                     <TextBlock Text="{Binding Name}" FontSize="20" Margin="4" FontWeight="Bold" VerticalAlignment="Center"/>
  11.                     <TextBlock Text="{Binding Author}" FontSize="16" Grid.Column="1" VerticalAlignment="Center" Margin="10,4,4,4" />
  12.                 </Grid>
  13.             </Border>
  14.         </DataTemplate>
  15.     </ListBox.ItemTemplate>
  16. </ListBox>

Running this sample with some of my favorite books, yields the following:

image

Note the lack of alignment. How can we fix this?

One simple solution is to replace the Width=”Auto” on the ColumnDefinition with a specific width, like so:

  1. <ColumnDefinition Width="200" />

This might work, but that’s very fragile. New book names might be wider, or the font size may change.

We could also try a “star” ratio, but again, this may or may not work correctly.

The Grid provides an elegant solution: a column’s width (or a row’s height) can share its size with other Grid objects under some parent container. That’s what’s required here, because the DataTemplate causes multiple Grid objects to be created at runtime under the ListBox. If we could somehow connect their columns’ width – we could get the desired effect.

The DefinitionBase class (base of ColumnDefinition and RowDefinition) provides a SharedSizeGroup property – a string that identifies columns/rows that should have the same size if they share the same value of SharedSizeGroup. In our case, the Grids are created by applying the DataTemplate, so the group name need only be specified once, and its exact value is unimportant:

  1. <ColumnDefinition Width="Auto" SharedSizeGroup="abc"/>

To make this work, there’s one more step: set the attached Grid.IsSharedSizeScope to true on some parent of those Grids, to set a context from which the strings may be distinguished. In our case, the ListBox control will do just fine:

  1. <ListBox HorizontalContentAlignment="Stretch" x:Name="_list" Grid.IsSharedSizeScope="True">

And that’s it.

image

Note that (unfortunately) Silverlight does not support this capability.

Comments List

No Comments

Leave a Comment

(required) 
(
required
)
 
(optional)
(required) 

Enter the numbers above: