2010-04-17 79 views
8

假设您有一个带有多个按钮的窗口,如确定/取消或是/否/取消。所有的按钮都需要相同的宽度。显然,这可以通过猜测一个数字并将它们全部硬连线到这个数字来完成。WPF按钮相同/推荐宽度

有没有更好的方法来做到这一点,一个会考虑到首选/推荐的尺寸(只要ok按钮有多宽?这不是一个修辞问题,我其实不知道答案! ),最长字幕文本需要什么,如果字体大小增加等等,会发生什么?

+0

请尽量不要硬编码UI尺寸等。考虑到国际化和(现在WPF使用'独立解决方案的单位')程度较小的各种规模和DPI屏幕是不好的做法。我们有布局面板供我们使用。他们很好。 – 2010-04-17 14:25:41

+0

按钮应该是50dlu x 23dlu。 WPF不支持对话单元;所以你几乎卡住了。 – 2011-08-21 03:50:24

回答

9

有几种方法可以做到这一点:

1)使用网格布局。每个Button都有自己的Star,它是Star的大小。这样一来,所有列的大小相同:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
    <Button Grid.Column="0">Yes</Button> 
    <Button Grid.Column="1">No</Button> 
    <Button Grid.Column="2">Cancel</Button> 
</Grid> 

2)你可以有一个项目为“主尺寸”和所有其他的宽度绑定到这个项目的宽度。

<StackPanel Orientation="Horizontal"> 
    <Button Name="MasterButton" Width="100">Yes</Button> 
    <Button> 
     <Button.Width> 
      <Binding ElementName="MasterButton" Path="Width"/> 
     </Button.Width> 
     No 
    </Button> 
</StackPanel> 

编辑:在实际的代码,你将可能有WIDTH = “自动”。由于其他宽度基于“主宽度”,应选择宽度最宽(最宽文本)的按钮。

+0

建议您在第一个建议中使用面板+1,但我真的反对硬编码的UI尺寸。 – 2010-04-17 14:27:31

+0

在第二种情况下,这是为了演示绑定正在工作。 – 2010-04-17 14:34:40

+5

统一网格不是一个好的解决方案吗? – henon 2011-09-23 09:20:28

0

在最常见的情况下,您想要在部分中创建 样式,然后根据需要应用此样式。现在,当您更改样式时,所有按钮都会更改。

或者您可以更改按钮的内容,使其自动调整为文本。

+0

谢谢。但是,纠正我,如果我错了,但不会使按钮自动大小的文字,打破所有按钮的宽度相同的要求?而且,是不是风格解决方案,只是一种实现“猜数字和硬连线所有按钮到这个数字”的特殊方式? – rwallace 2010-04-17 13:54:08

+0

啊......我明白你的要求了,对不起!那么丹尼尔有更好的答案。 – Dave 2010-04-17 14:16:13

2

根据用于Windows 7和Windows Vista的MS用户体验交互准则(p61),命令按钮的标准尺寸为50x14 DLU实际尺寸(75x23像素)。指南还建议您“尝试使用[这些]默认宽度和高度。”很明显,如果你需要更多的宽度来适应清晰的标签,那么需要更多的宽度。

+0

按钮应该是50x14对话单元。你转换为像素是错误的;至少在我的计算机上,我使用'格鲁吉亚14pt'。这就是对话单元存在的原因 - 所以人们停止使用像素大小。 – 2011-08-21 03:50:07

4

在丹尼尔的答案中使用“主”控制一样,但绑定到“ActualWidth的”属性而不是“宽”:

<StackPanel Orientation="Horizontal"> 
    <Button Name="MasterButton">Yes</Button> 
    <Button> 
     <Button.Width> 
      <Binding ElementName="MasterButton" Path="ActualWidth"/> 
     </Button.Width> 
     No 
    </Button> 
</StackPanel> 

这样,该值从运行主控取时间,在考虑了最小和最大宽度以及所有其他布局计算之后。绑定到“宽度”会绑定到在编译时放入属性的任何东西,这可能不是真正使用的宽度。

此外,绑定可以写成较短像

<Button Width="{Binding ElementName=MasterButton, Path=ActualWidth}"/> 
7

另一个,也许更简单,方式做到这一点是使用SharedSizeGroup财产上的ColumnDefinitionRowDefinition类。

WPF Grid中的列(和行)可以自动调整大小以适应其内容 - 当使用SharedSizeGroup时,具有相同组名的列共享其调整逻辑。

Xaml看起来像这样...

<Grid Grid.IsSharedSizeScope="True"> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <Button Grid.Column="1" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Ok" 
      Margin="4" /> 

    <Button Grid.Column="2" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Cancel" 
      Margin="4" /> 

    <Button Grid.Column="3" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Long Button Caption" 
      Margin="4" /> 
</Grid> 
0

这些答案都是伟大的,如果你有一个按钮固定数量或固定的布局,但如果像我一样有来自约束力和包含在ItemsControl那么这是不可行的到来按钮的动态数量。但是有一个简单的方法,它仍然涉及使用Grid的sharedsize属性。

的DataTemplate:

<DataTemplate x:Key="ODIF.Mapping"> 
    <Button HorizontalContentAlignment="Left" Background="#FFEEEEEE" BorderBrush="#FFBDBDBD"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto" SharedSizeGroup="PluginButtonsWidth"/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto" SharedSizeGroup="PluginButtonsIconHeight"/> 
       <RowDefinition Height="Auto" SharedSizeGroup="PluginButtonsNameHeight"/> 
      </Grid.RowDefinitions> 
      <Image Width="32" Height="32" Source="{Binding PluginIcon}" RenderOptions.BitmapScalingMode="HighQuality"/> 
      <TextBlock Grid.Row="1" Text="{Binding PluginName}"/> 
     </Grid> 
    </Button> 
</DataTemplate> 

父容器:

<ItemsControl ItemsSource="{Binding MappingPlugins, ElementName=page}" ItemTemplate="{StaticResource ODIF.Mapping}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <WrapPanel Grid.IsSharedSizeScope="True"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

本质上按钮的内容本身可以是网格,然后根据需要,你可以把你的标签和图标,但即使按钮不要驻留在同一个网格中(它们都是自己的网格),只要将根容器的(ItemsControl)属性Grid.IsSharedSizeScope设置为True,网格仍可以共享它的大小。

这将强制每个按钮的内容网格基于最大的同一确切大小,而不必将按钮本身放在预定义的网格中。