WPF: Можно ли установить ширину элемента по процентам?
Скажем, у меня есть 2 кнопки в элементе, и я хочу, чтобы 2 элемента всегда заполняли 1/2 ширины его содержащего элемента каждый, могу ли я сделать это?
UPDATE
почему я не могу сделать что-то вроде
<StackPanel Orientation="Horizontal" Grid.Row="0">
<Button Content="Click me" Command="{Binding ClickCommand}" Width="1*" />
<Button Content="Exit" Command="{Binding CloseCommand}" Width="1*" />
</StackPanel>
Почему в этом контексте не работает 1 *? я получаю ошибку
Невозможно преобразовать "1 *"
Ответы
Ответ 1
Для этого можно использовать Grid
с двумя столбцами.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0">Button1</Button>
<Button Grid.Column="1">Button2</Button>
</Grid>
Обратите внимание на использование звезды (*
) в свойстве ColumnDefinition.Width
. Это означает, что оба столбца занимают одинаковое пространство. Таким образом, в приведенном выше примере каждая кнопка будет занимать 1/2 от доступного пространства содержащего Grid
. Поэтому, если вы сделаете один Width
равным 2*
, этот столбец займет в два раза больше места, чем другой столбец. Надеюсь, это имеет смысл.
Ответ 2
Я создал ContentControl, который позволяет мне обернуть контент, чтобы добавить динамическую процентную ширину/высоту.
/// <summary>
/// This control has a dynamic/percentage width/height
/// </summary>
public class FluentPanel : ContentControl, IValueConverter
{
#region Dependencie Properties
public static readonly DependencyProperty WidthPercentageProperty =
DependencyProperty.Register("WidthPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, WidthPercentagePropertyChangedCallback));
private static void WidthPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
((FluentPanel)dependencyObject).OnWidthPercentageChange();
}
public int WidthPercentage
{
get { return (int)GetValue(WidthPercentageProperty); }
set { SetValue(WidthPercentageProperty, value); }
}
public static readonly DependencyProperty HeightPercentageProperty =
DependencyProperty.Register("HeightPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, HeightPercentagePropertyChangedCallback));
private static void HeightPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
((FluentPanel)dependencyObject).OnHeightPercentageChanged();
}
public int HeightPercentage
{
get { return (int)GetValue(HeightPercentageProperty); }
set { SetValue(HeightPercentageProperty, value); }
}
#endregion
#region Methods
private void OnWidthPercentageChange()
{
if (WidthPercentage == -1)
{
ClearValue(WidthProperty);
}
else
{
SetBinding(WidthProperty, new Binding("ActualWidth") { Source = Parent, Converter = this, ConverterParameter = true });
}
}
private void OnHeightPercentageChanged()
{
if (HeightPercentage == -1)
{
ClearValue(HeightProperty);
}
else
{
SetBinding(HeightProperty, new Binding("ActualHeight") { Source = Parent, Converter = this, ConverterParameter = false });
}
}
#endregion
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((bool)parameter)
{
// width
return (double)value * (WidthPercentage * .01);
}
else
{
// height
return (double)value * (HeightPercentage * .01);
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}