thitemple
thitemple

Reputation: 6059

How to have buttons with the same width inside a ListView/WrapPanel?

I have a ListView that shows a list of buttons inside a WrapPanel. The text inside the buttons may vary so the width of the buttons may also vary.

I'd like to have all the buttons to have same width, meaning I want all the buttons to have the width of the larger button inside the WrapPanel. Is there a way to do that?

Here's my ListView:

<ListView Margin="8 10 8 8"
                      VerticalAlignment="Top"
                      ScrollViewer.CanContentScroll="True"
                      Background="Transparent"
                      x:Name="ResourcesList"
                      BorderThickness="0"
                      ItemContainerStyle="{DynamicResource LvItemStyle}"
                      ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                      ItemsSource="{Binding CadResource.Values}">
                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel HorizontalAlignment="Left" />
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>
                <ListView.ItemTemplate>
                    <ItemContainerTemplate>
                        <Button Content="{Binding ResourceAlias.Value}"
                                x:Name="ResourceButton"
                                Command="{Binding ElementName=ResourcesList, Path=DataContext.SelectResourceCommand}"
                                CommandParameter="{Binding}"
                                VerticalContentAlignment="Stretch"
                                BorderThickness="0"
                                Margin="2"
                                MinWidth="75"
                                Template="{DynamicResource ResourceButtonTemplate}"
                                Foreground="{DynamicResource ResouceAliasText}"
                                Background="{Binding ResourceAlias.BackColor, Mode=TwoWay, Converter={converter:StringFormatConverter}}">
                            <Button.ContextMenu>
                                <ContextMenu Name="ContextMenu"

                                             ItemsSource="{Binding ContextMenu}"
                                             ItemContainerStyle="{StaticResource MenuItemStyle}" />
                            </Button.ContextMenu>
                        </Button>
                    </ItemContainerTemplate>
                </ListView.ItemTemplate>
            </ListView>

And here's the template for the button that I'm using:

<ControlTemplate x:Key="ResourceButtonTemplate"
                     TargetType="{x:Type ButtonBase}">
        <Border x:Name="border"
                Background="{DynamicResource ResourceButtonBackground}"
                BorderThickness="1"
                Height="20"
                BorderBrush="{DynamicResource ResourceButtonBorder}"
                SnapsToDevicePixels="True">
            <Border BorderThickness="0 1 0 0"
                    Background="Transparent"
                    BorderBrush="{DynamicResource ResourceHighlight}">
                <Grid>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <images:ResourceSquare Fill="{TemplateBinding Background}"
                                           Grid.Column="0"
                                           Style="{StaticResource ViewBoxStyleChildWindow13X13}"
                                           x:Name="ResourceSquare"
                                           HorizontalAlignment="Left"
                                           Margin="3 2 0 2" />

                    <images:ResourceTriangle Fill="{TemplateBinding Background}"
                                             Grid.Column="0"
                                             Style="{StaticResource ViewBoxStyleChildWindow13X13}"
                                             x:Name="ResourceTriangle"
                                             Visibility="Collapsed"
                                             HorizontalAlignment="Left"
                                             Margin="3 2 0 2" />

                    <ContentPresenter x:Name="contentPresenter"
                                      Grid.Column="1"
                                      ContentTemplate="{TemplateBinding ContentTemplate}"
                                      Content="{TemplateBinding Content}"
                                      ContentStringFormat="{TemplateBinding ContentStringFormat}"
                                      Focusable="False"
                                      TextBlock.FontSize="{Binding FontSize}"
                                      Margin="7 0 7 0"
                                      RecognizesAccessKey="True"
                                      HorizontalAlignment="Center"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />

                    <images:ResourceConnected Fill="{DynamicResource IconToolbar}"
                                              Grid.Column="2"
                                              Style="{StaticResource ViewBoxStyleChildWindow10X10}"
                                              HorizontalAlignment="Right"
                                              VerticalAlignment="Top" />
                </Grid>
            </Border>
        </Border>
        <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding IsSelected.Value}"
                         Value="True">
                <Setter TargetName="border"
                        Property="Background"
                        Value="{DynamicResource ListSelectedLine}" />
                <Setter TargetName="border"
                        Property="BorderBrush"
                        Value="{DynamicResource BorderHighLight}" />
            </DataTrigger>
            <Trigger Property="Button.IsDefaulted"
                     Value="True">
                <Setter Property="BorderBrush"
                        TargetName="border"
                        Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
            </Trigger>
            <Trigger Property="IsMouseOver"
                     Value="True">
                <Setter Property="Background"
                        TargetName="border"
                        Value="{DynamicResource CadMouseOver}" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

Upvotes: 0

Views: 573

Answers (2)

thitemple
thitemple

Reputation: 6059

So here's what I did:

I added an event handler for SizeChanged on the WrapPanel

<WrapPanel HorizontalAlignment="Left" SizeChanged="WrapPanelSizeChanged" />

And the WrapPanelSizeChanged is as follows:

private void WrapPanelSizeChanged(object sender, EventArgs e)
{
    var panel = sender as WrapPanel;
    if(panel == null)
        return;
    if( panel.Children.Count == 0 )
        return;
    var itemWidth = panel.Children.OfType<FrameworkElement>().Max(x => x.ActualWidth);
    panel.ItemWidth = itemWidth;
}

Upvotes: 1

Liero
Liero

Reputation: 27360

Well, the control you need is called WrapGrid. It is present in Windows Store apps, but not in WPF. Somebody calls it UniformWrapPanel. See this please: Is there a WPF "WrapGrid" control available or an easy way to create one?

Please note, that WrapPanel has ItemWidth property. If you set it, all child elements will have this width. It would be very easy, if you could set it to fixed value.

You can try following. Add items to wrappanel, then measure theirs sizes, select widest element and set it's ActualWidth to WrapPanel.ItemWidth property. Then all elements should have the same width

Upvotes: 0

Related Questions