【问题标题】:WPF buttons same/recommended widthWPF 按钮相同/推荐宽度
【发布时间】:2010-04-17 13:36:39
【问题描述】:

假设您有一个带有多个按钮的窗口,例如确定/取消或是/否/取消。所有按钮的宽度必须相同。显然,这可以通过猜测一个数字并将它们全部连接到该数字来完成。

有没有更好的方法,可以考虑首选/推荐的尺寸(确定按钮到底应该有多宽?这不是一个修辞问题,我实际上不知道答案!) ,最长标题的文字需要什么,如果增加字体大小会发生什么?

【问题讨论】:

  • 请尽量不要硬编码 UI 大小等。考虑到国际化和(在较小程度上现在 WPF 使用“分辨率独立单位”)各种尺寸和 DPI 屏幕时,这是不好的做法。我们有可供我们使用的布局面板。他们很好。
  • 按钮应该是 50dlu x 23dlu。 WPF 不支持对话单元;所以你几乎被困住了。

标签: wpf user-interface


【解决方案1】:

另一种可能更简单的方法是在ColumnDefinitionRowDefinition 类上使用SharedSizeGroup 属性。

WPF 网格中的列(和行)可以自动调整大小以适应其内容 - 当使用 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>

【讨论】:

    【解决方案2】:

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

    1) 使用 Grid 进行布局。每个 Button 都有自己的 Column,它是 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="Auto"。由于其他宽度都是基于“主宽度”,所以应该选择宽度最宽的按钮(最宽的文字)。

    【讨论】:

    • +1 建议在您的第一个建议中使用面板,但我真的反对硬编码 UI 尺寸。
    • 在第二种情况下,这是为了证明绑定正在工作。
    • 文本宽度最宽的按钮可能在不同语言中是不可预测的。有没有办法让所有按钮的宽度相同,允许最长的文本来指示它是什么,不管是哪个按钮?
    • @AndrewArnott 在这种情况下,请使用网格布局,就像我的答案的第一个变体或 Bevan 的答案一样。
    • 是的,我选择了Bevan's answer,因为它允许所有按钮的宽度相同,而无需假设整个对话框的宽度或最宽的按钮。
    【解决方案3】:

    使用“主”控件,就像丹尼尔的回答一样,但绑定到“ActualWidth”属性而不是“Width”:

    <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}"/>
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 按钮应该是 50x14 对话单元。您转换为像素是错误的;至少在我使用Georgia 14pt的电脑上。这就是对话单元存在的原因——因此人们不再使用像素大小。
      【解决方案5】:

      如果您有固定数量或固定布局的按钮,这些答案非常好,但如果像我一样有来自绑定并包含在 ItemsControl 中的动态数量的按钮,那么这是不可行的。但是有一个简单的方法,它仍然涉及使用 Grid 的 sharedsize 属性。

      数据模板:

      <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>
      

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

      这将强制每个按钮的内容网格与最大的按钮的大小完全相同,而不必将按钮本身放在预定义的网格中。

      【讨论】:

        【解决方案6】:

        在最一般的情况下,您希望创建一个 在您的部分中设置样式,然后根据需要应用此样式。现在,当您更改样式时,所有按钮都会更改。

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

        【讨论】:

        • 谢谢。但是,如果我错了,请纠正我,但不会让按钮自动调整到文本大小,打破所有按钮宽度相同的要求吗?而且,样式解决方案不就是一种实现“猜一个数字并将所有按钮硬连线到该数字”的特定方式吗?
        • 啊...我现在明白你的要求了,对不起!那么丹尼尔有一个更好的答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-26
        相关资源
        最近更新 更多