WPF кнопки одинаковые / рекомендуемая ширина

Предположим, у вас есть окно с несколькими кнопками, такими как Ok/Cancel или Yes/No/Cancel. Все кнопки должны быть одинаковой ширины. Очевидно, что это можно сделать, просто угадав число и подключив их всех к этому числу.

Есть ли лучший способ сделать это, который бы учитывал предпочтительные / рекомендуемые размеры (насколько широкой должна быть кнопка Ok в любом случае? Это не риторический вопрос, я на самом деле не знаю ответа!), Что нужно по тексту самой длинной надписи, что произойдет, если размер шрифта увеличится и т. д.?

6 ответов

Решение

Есть несколько способов сделать это:

1) Используйте сетку для макета. Каждая кнопка имеет свой собственный столбец, который имеет размер звезды. Таким образом, все столбцы имеют одинаковый размер:

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

РЕДАКТИРОВАТЬ: В реальном коде, вы, вероятно, будете иметь ширину = "Авто". Поскольку другие значения ширины основаны на "основной ширине", следует выбирать кнопку с самой широкой шириной (самый широкий текст).

Другой, возможно, более простой способ сделать это - использовать SharedSizeGroup собственность на ColumnDefinition а также RowDefinition классы.

Столбцы (и строки) в сетке 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>

Используйте "главный" элемент управления, как в ответе Даниэля, но связывайте с атрибутом "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}"/>

В соответствии с Руководством по взаимодействию с пользователем в MS 7 для Windows 7 и Windows Vista (p61) стандартные размеры для командных кнопок составляют фактический размер 50x14 DLU (75x23 пикселей). Рекомендации также предлагают вам "попытаться работать с [этими] значениями ширины и высоты по умолчанию". Очевидно, что если вам нужно больше ширины, чтобы разместить четкую метку, тогда берите больше ширины.

Эти ответы хороши, если у вас есть фиксированное число или фиксированное расположение кнопок, но если вы, как и я, есть динамическое количество кнопок, происходящих из привязки и содержащихся в 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>

По сути, содержимое кнопки само по себе может представлять собой Gird, в котором вы можете размещать ярлыки и значки по мере необходимости, но даже при том, что кнопки не находятся в одной и той же сетке (каждая из них является своей), сетка все еще может иметь такой же размер как вы устанавливаете корневой контейнер (ItemsControl) собственностью Grid.IsSharedSizeScope к Истине.

Это приведет к тому, что сетка содержимого каждой кнопки будет иметь одинаковый точный размер, основанный на самой большой из них, при этом нет необходимости размещать сами кнопки в предварительно определенной сетке.

В наиболее общем случае вы хотите создать стиль в своем разделе, а затем применить этот стиль по желанию. Теперь, когда вы меняете стиль, меняются все кнопки.

Или вы можете изменить содержимое кнопки, чтобы она автоматически изменяла размер текста.

Другие вопросы по тегам