根据最大按钮的内容均匀大小的按钮

Posted

技术标签:

【中文标题】根据最大按钮的内容均匀大小的按钮【英文标题】:Evenly-sized buttons according to content of largest button 【发布时间】:2011-09-09 03:32:12 【问题描述】:

假设我在一个窗口上有两个 WPF 按钮,内容如下:

<Button>OK</Button>
<Button>Cancel</Button>

我希望这些按钮具有相同的宽度,但是在 Content 绑定到给定用户语言的本地化值的情况下,我不知道按钮需要多宽才能适应新的内容。

我如何为这些按钮应用最小宽度,以便最宽的宽度(根据内容)有效地用作两者的MinWidth,从而保持它们一致?

或者换一种说法:我不希望按钮成为其容器的宽度(除非以巧妙的方式使用容器可以解决我的问题),并且我不希望它们每个都只需根据自己的内容调整大小,因为这会使它们的大小不同。我想要介于两者之间的东西。具有最大内容大小以显示其内容的内容,以及所有其他内容大小相同的宽度,因此宽度都相等。

我希望答案在于将它们放入某种容器中。我知道我可以使用Grid 并让它们填充网格“单元格”,但重点是我也不希望它们 宽。我知道我可以在按钮的Content_Changed 事件上运行一些代码隐藏并将最小宽度设置为最宽按钮的最小宽度,但我对纯xaml 方法感兴趣。我可能需要创建一个扩展 ItemsControl 的自定义控件,以便在添加新项目或调整其大小时运行代码隐藏并将最宽项目的宽度应用为所有其他项目的 MinWidth

非常感谢。

【问题讨论】:

所以你是说你不想使用 并设置 Buttons Width="Auto"? 我不希望按钮成为其容器的宽度(除非以巧妙的方式使用容器是我的问题的答案),并且我不希望它们的大小适合他们的内容,因为这会使它们的大小不同。我想要介于两者之间的东西。具有最大内容大小以显示其内容的内容,以及所有其他内容大小相同的内容,因此宽度都相等。 那么我猜你的按钮都分散在你的视图上,因为如果没有,并且它们都被分组,那么 ColumnDefinition 就可以了。如果他们都分散了,我也想知道一个很好的解决你的问题的方法。 =) 不,它们位于水平对齐的堆栈面板中,采用经典的“OK”、“Cancel”设计。我认为 H.B. 下面的回答 (***.com/questions/6249946/…) 实际上就是你所说的,我只是没有从你的评论中真正理解你的意思。 :) @Willem &lt;ColumnDefinition Width="*"/&gt; 不需要 "Auto" 【参考方案1】:

网格

  <Grid HorizontalAlignment="Right" Grid.IsSharedSizeScope="true">
    <Grid.ColumnDefinitions>
        <ColumnDefinition SharedSizeGroup="A"/>
        <ColumnDefinition SharedSizeGroup="A"/>
    </Grid.ColumnDefinitions>
    <Grid.Children>
        <Button Grid.Column="0" Content="OK"/>
        <Button Grid.Column="1" Content="Cancel"/>
    </Grid.Children>
  </Grid>

这可以分解,你只需要在一个共同的祖先上设置IsSharedSizeScope,例如:

    <StackPanel Grid.IsSharedSizeScope="true">
        <Grid HorizontalAlignment="Right">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="A"/>
            </Grid.ColumnDefinitions>
            <Grid.Children>
                <Button Grid.Column="0" Content="OK"/>
            </Grid.Children>
        </Grid>
        <!-- ... -->
        <Grid HorizontalAlignment="Left">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="A"/>
            </Grid.ColumnDefinitions>
            <Grid.Children>
                <Button Grid.Column="0" Content="Cancel"/>
            </Grid.Children>
        </Grid>
    </StackPanel>

为防止按钮变得太大,请将网格的HorizontalAlignment 更改为Stretch 以外的其他值或设置MaxWidth

【讨论】:

你展示的使用 SharedSizeGroup 的方式我认为比作者接受的答案更有用。谢谢。【参考方案2】:
Use UniformGrid

<UniformGrid HorizontalAlignment="Right" Rows="1" Columns="2">
  <Button Content="Ok" Grid.Column="0"/>
  <Button Content="Cancel" Grid.Column="1"/>
</UniformGrid>

【讨论】:

这个答案的优点是允许您为不需要的按钮设置 Visibility = "Collapsed" 并且整个单元格消失 - 使用 SharedSizeGroup 网格这样做会给您留下一个洞,这可能不是你想要的。加上它的简洁! Grid.ColumnGrid.RowUniformGrid 忽略,在 Xaml 中按声明顺序添加控件。【参考方案3】:

我喜欢在这种情况下使用包装面板。加载后,我使用linq 从所有孩子那里获得最大宽度。 (假设孩子都是按钮)

xaml

<WrapPanel Name="WP_ButtonSelections" Orientation="Horizontal" HorizontalAlignment="Center" Loaded="WP_ButtonSelections_Loaded"></WrapPanel>

cs

WP_ButtonSelections.Children.Add(new Button()  Content = "Hello" );
WP_ButtonSelections.Children.Add(new Button()  Content = "Hello World" );


private void WP_ButtonSelections_Loaded(object sender, RoutedEventArgs e)

   double maxWidth = WP_ButtonSelections.Children.OfType<FrameworkElement>().Max(elm => elm.ActualWidth);
   WP_ButtonSelections.Children.OfType<FrameworkElement>().ToList().ForEach(elm => elm.Width = maxWidth);

我需要一个程序化解决方案。这需要加载事件,因为以编程方式添加的按钮不会在调用WP_ButtonSelections.Children.Add() 时定义ActualWidth。此解决方案应该使用 xaml 定义的按钮,或者 xaml 和编程的混合。

【讨论】:

以上是关于根据最大按钮的内容均匀大小的按钮的主要内容,如果未能解决你的问题,请参考以下文章

布局中的等距按钮

如何根据其文本调整按钮的大小

如何在自动布局中设置视图下方不同数量按钮的宽度

WPF - 折叠网格单元

如何根据屏幕大小调整按钮的图像和文本大小(自动布局)

根据屏幕大小缩放图像按钮