WPF: установка ширины (и высоты) в процентах
Скажите, что я хочу, чтобы TextBlock
имел свой Width
равный ему родительский контейнер Width
(т.е. растягивался из стороны в сторону) или процент от него Parent Container Width
, как я могу выполнить это в XAML
без указания абсолютных значений?
Я хочу сделать это, чтобы, если контейнер родительского контейнера позже расширится (его "Width
увеличено), его" дочерние элементы "также будут автоматически расширены. (в основном, как в HTML и CSS)
Ответы
Ответ 1
Способ растянуть его до того же размера, что и родительский контейнер, должен использовать атрибут:
<Textbox HorizontalAlignment="Stretch" ...
Это заставит элемент Textbox растягиваться горизонтально и заполнить все родительское пространство по горизонтали (на самом деле это зависит от используемой родительской панели, но должно работать в большинстве случаев).
Проценты могут использоваться только со значениями ячейки сетки, поэтому другой вариант заключается в создании сетки и помещении вашего текстового поля в одну из ячеек с соответствующим процентом.
Ответ 2
Это обновленный ответ на мой предыдущий пост от '09 и содержащий неверную информацию. Следующий пример должен быть лучше:
Вы можете поместить текстовые поля внутри сетки, чтобы делать процентные значения в строках или столбцах сетки, и позволить текстовым полям автоматически заполнять их родительские ячейки (как они будут по умолчанию). Пример:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" />
<TextBox Grid.Column="1" />
</Grid>
Это сделает № 1 2/5 ширины и # 2 3/5.
Исходное сообщение с неправильной/неполной информацией
Не думайте, что вы можете сделать%, но вы можете сделать *:)
Пример:
<TextBox width="2*"/>
<TextBox width="3*"/>
Это сделает № 1 2/5 ширины и # 2 3/5.
Ответ 3
Как правило, вы должны использовать встроенный макет, соответствующий вашему сценарию (например, использовать сетку в качестве родителя, если вы хотите масштабирование относительно родителя). Если вы хотите сделать это с помощью произвольного родительского элемента, вы можете создать ValueConverter, но это, вероятно, будет не так чисто, как вам хотелось бы. Однако, если вы в ней абсолютно нуждаетесь, вы можете сделать что-то вроде этого:
public class PercentageConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
return System.Convert.ToDouble(value) *
System.Convert.ToDouble(parameter);
}
public object ConvertBack(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Что можно использовать так, чтобы получить дочернее текстовое поле на 10% от ширины его родительского холста:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:PercentageConverter x:Key="PercentageConverter"/>
</Window.Resources>
<Canvas x:Name="canvas">
<TextBlock Text="Hello"
Background="Red"
Width="{Binding
Converter={StaticResource PercentageConverter},
ElementName=canvas,
Path=ActualWidth,
ConverterParameter=0.1}"/>
</Canvas>
</Window>
Ответ 4
Для любого, кто получает ошибку, например: '2 *' строка не может быть преобразована в длину.
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" /><!--This will make any control in this column of grid take 2/5 of total width-->
<ColumnDefinition Width="3*" /><!--This will make any control in this column of grid take 3/5 of total width-->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="30" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0">Your text block a:</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="0">Your text block b:</TextBlock>
</Grid>
Ответ 5
Я использую два метода для относительного размера. У меня есть класс под названием Relative
с тремя прикрепленными свойствами To
, WidthPercent
и HeightPercent
, который полезен, если я хочу, чтобы элемент был относительным размером элемента в любом месте визуального дерева и чувствовал себя менее взломанным, чем конвертер подход - хотя использовать то, что работает для вас, что вы довольны.
Другой подход более хитер. Добавьте ViewBox
, где вы хотите относительные размеры внутри, а затем внутри, добавьте Grid
шириной 100. Затем, если вы добавите TextBlock
с шириной 10 внутри, это, очевидно, 10% от 100.
ViewBox
будет масштабировать Grid
в соответствии с любым пространством, которое оно было задано, поэтому, если это единственное, что отображается на странице, то Grid
будет масштабироваться по всей ширине и эффективно, ваш TextBlock
масштабируется до 10% страницы.
Если вы не установите высоту на Grid
, тогда она будет уменьшаться, чтобы соответствовать ее контенту, поэтому все будет относительно небольшим. Вы должны будете убедиться, что контент не становится слишком высоким, т.е. Начинает изменять соотношение сторон пространства, указанного в ViewBox
, иначе он начнет масштабировать высоту. Вероятно, вы можете обойти это с помощью Stretch
UniformToFill
.
Ответ 6
Я знаю, что это не Xaml, но я сделал то же самое с событием SizeChanged в текстовом поле:
private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
TextBlock textBlock = sender as TextBlock;
FrameworkElement element = textBlock.Parent as FrameworkElement;
textBlock.Margin = new Thickness(0, 0, (element.ActualWidth / 100) * 20, 0);
}
Текстовое поле, по-видимому, составляет 80% от его родительского (нужный правый край составляет 20%) и растягивается при необходимости.
Ответ 7
ConverterClass:
public class SizePercentageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null)
return 0.7 * value.ToDouble();
string[] split = parameter.ToString().Split('.');
double parameterDouble = split[0].ToDouble() + split[1].ToDouble() / (Math.Pow(10, split[1].Length));
return value.ToDouble() * parameterDouble;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Don't need to implement this
return null;
}
}
XAML:
<UserControl.Resources>
<m:SizePercentageConverter x:Key="PercentageConverter" />
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Width="{Binding Converter={StaticResource PercentageConverter}, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualWidth}"
Height="{Binding Converter={StaticResource PercentageConverter}, ConverterParameter=0.6, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}">
....
</ScrollViewer>