Question

Hopefully no one else has already asked this question, but I have searched and cannot find any mention. Feel free to point me in the right direction if I missed another question that explains this.

I have a WrapPanel with data-bound items that essentially contain an icon and some variable length text (this is a legend for a chart). I really like the fact that the items appear in neat columns when I set the ItemWidth to some set value. However, due to the high variability in length of the text in each item, I cannot easily choose a specific value that will work for all cases. That is, in some cases the text for all the items might be short, so a smaller value for ItemWidth would be appropriate. But other times, such a small ItemWidth would result in truncated text among some of the items.

I figure I can data bind ItemWidth to the WrapPanel's children somehow in order to extract the width of each item (and find the maximum width, and use that as the ItemWidth, etc), but I am leery of doing so due to the potential of data binding to the wrong thing. As in, binding to something that changes when ItemWidth changes, leading to infinite loops (or at least, loops that repeat more times than necessary.

What is the best way to set this so that the ItemWidth is only as large as it needs to be to prevent truncation?

EDIT:

I want to retain the feature offered by the WrapPanel that allows there to be a variable number of columns of items, depending on the space allowed for the WrapPanel itself.

Was it helpful?

Solution

You could wrap each item in a Grid, and use the Grid's ShareSizeScope property to make sure all items share the same width.

For example, on your WrapPanel you would set Grid.IsSharedSizeScope to true

<WrapPanel Grid.IsSharedSizeScope="True">

Then you'd wrap each item in a single cell Grid that uses the SharedSizeGroup property to tell them that they all share a size

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition SharedSizeGroup="SharedGroup" />
    </Grid.ColumnDefinitions>
    <ContentPresenter />
</Grid>

If you want an example, a quick Google search gave me this answer which contains a code example.

I'd recommend performance testing this too if you have a large set of data.

OTHER TIPS

Try the following. The part to pay attention to is the Grid.IsSharedSizeScope="True" on the wrap panel AND the column definition's SharedSizeGroup property.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <WrapPanel Grid.IsSharedSizeScope="True">
            <WrapPanel.Resources>
                <Style TargetType="TextBlock">
                    <Setter Property="Padding" Value="2" />
                    <Setter Property="HorizontalAlignment" Value="Center" />
                </Style>
            </WrapPanel.Resources>
            <WrapPanel.Children>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="abcdefghijklmnopqrstuvwxyz" />
                </Grid>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="group1" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="1234567890" />
                </Grid>
            </WrapPanel.Children>
        </WrapPanel>
    </Grid>
</Window>

try setting the itemwidth property to Auto... see here:

http://msdn.microsoft.com/en-us/library/system.windows.controls.wrappanel.itemwidth(v=vs.110).aspx

to perform this "width set" programmatically, you could do the following, once the control has been rendered.

protected override void OnRender(DrawingContext dc)
{

int largest = 0;
foreach(UIElement child in this.myWrapPanel.Children)
{
    if(child.Width>largest)
        largest = child.Width;
}

this.myWrapPanel.ItemWidth = largest;


}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top