#wpf #xaml #button #grid
#wpf #xaml #кнопка #сетка
Вопрос:
Я выравниваю элементы управления (кнопки) моего пользовательского интерфейса с помощью сетки.
Важно, чтобы размер кнопок максимально заполнял ячейку И соблюдалось соотношение, чтобы мои кнопки оставались круглым кругом.
Я выбрал сетку, так как управление размером кнопки с помощью ячейки сетки при изменении размера окна кажется хорошим выбором, чтобы избежать кодирования.
Однако сейчас я борюсь с сохранением соотношения кнопок. Единственный способ, который работал до сих пор, заключался в том, чтобы обернуть мою кнопку в поле просмотра с помощью Stretch=»Uniform». Это нежизнеспособный способ, так как содержимое кнопок тоже будет растянуто / увеличено, что сделает текст слишком большим, см. Скриншот
Я предполагаю, что другим решением может быть использование изображения или svg для круглой кнопки вместо фона с радиусом границы, поскольку они будут преобразованы таким образом, чтобы их соотношение сохранялось автоматически? Однако, если бы я это сделал, мне пришлось бы найти способ добавить текст сверху. Другой возможностью может быть убедиться, что ячейки таблицы всегда имеют одинаковую высоту / ширину? Похоже, это не так-то просто сделать.
Моим предпочтительным решением, если это возможно, было бы продолжать использовать фон с радиусом границы.
...
x:Key="RoundHoverButtonStyle"
BasedOn="{StaticResource StandardButtonStyle}"
TargetType="{x:Type Button}">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="100" />
</Style>
</Style.Resources>
...
<Grid Grid.Column="0" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox Stretch="Uniform">
<Button
x:Name="Button0"
Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Black"
Content="{Binding Path=ButtonConfigModel.ButtonDict[Button0].DisplayName}"
Foreground="White"
Style="{StaticResource RoundHoverButtonStyle}"
Tag="{Binding Path=ButtonConfigModel.ButtonDict[Button0].VirtualKey}"
Visibility="{Binding Path=ButtonConfigModel.ButtonDict[Button0].IsEnabled, Converter={StaticResource BoolToVis}}" />
</Viewbox>
...
Ответ №1:
Я думаю, что для вас подойдет работа с многозначным преобразователем, который затем связывается с высотой и шириной кнопки. А высота и ширина кнопки будут многократно привязаны к окружению DockPanel
. Это звучит сбивающе с толку — и это немного так. Но я думаю, что нижеприведенное внесет ясность. Я уверен, что есть более одного способа сделать это, но это работает для меня:
Во-первых, в вашем .cs
файле для вашего окна добавьте этот многозначный преобразователь — я помещаю свой в конец файла.
[ValueConversion(typeof(double), typeof(double))]
public class HeightWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double width = (double) values[0];
double height = (double) values[1];
return height - width <= 0 ? height : width;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
Обратите внимание, что этот преобразователь значений упрощен — вы должны добавить некоторые проверки, чтобы убедиться, что предоставлена правильная информация, чтобы предотвратить получение исключения like InvalidCast
или какого-либо другого исключения.
Затем в окне.Раздел Ресурсы вам нужно будет добавить ссылку на этот преобразователь значений:
<local:HeightWidthConverter x:Key="HeightWidthConverter"/>
Предполагается, что у вас есть атрибут xmlns с именем local, который ссылается на пространство имен вашего окна. Это будет выглядеть примерно так:
xmlns:local="clr-namespace:MyApp"
наконец, каждая кнопка будет обернута символом a DockPanel
, а высота и ширина кнопки будут привязаны к фактической высоте и фактической ширине DockPanel
, как это:
<Grid
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel x:Name="dp11"
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
>
<Button x:Name="Button11"
Content="Hello"
Background="Black"
Foreground="White"
FontSize="10"
Style="{DynamicResource RoundHoverButtonStyle}">
<Button.Width>
<MultiBinding Converter="{StaticResource HeightWidthConverter}">
<Binding ElementName="dp11" Path="ActualHeight" />
<Binding ElementName="dp11" Path="ActualWidth" />
</MultiBinding>
</Button.Width>
<Button.Height>
<MultiBinding Converter="{StaticResource HeightWidthConverter}">
<Binding ElementName="dp11" Path="ActualHeight" />
<Binding ElementName="dp11" Path="ActualWidth" />
</MultiBinding>
</Button.Height>
</Button></DockPanel>
<Grid.Resources>
<Style x:Key="RoundHoverButtonStyle"
TargetType="Button"
>
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="100" />
</Style>
</Style.Resources>
</Style>
</Grid.Resources>
</Grid>
Хитрость здесь в том, что MultiConverter
получает как фактическую ширину, так и фактическую высоту DockPanel
. Затем он определяет, какой из них меньше, и возвращает это значение. И, поскольку он выполняет одинаковые вычисления как для высоты, так и для ширины кнопки, кнопка будет иметь одинаковые значения высоты и ширины. Кроме того, поскольку DockPanel
изменение размеров соответствует окружающей сетке (при условии, что эта способность реализована), Button
она также автоматически изменит размер.
Используя этот метод, каждая кнопка будет иметь одинаковую высоту и ширину (т.е. Быть круглой).
Причина переноса кнопки в a DockPanel
заключается в том, что она будет отображаться / изменяться перед кнопкой, и поэтому кнопка будет иметь значения размера для работы (кстати, это очень большое упрощение). Кроме того, я обнаружил DockPanel
, что a лучше справляется с заполнением себя в пределах доступного пространства, чем a StackPanel
.