WPF: Встановлення ширини (і висоти) як процентне значення


149

Скажіть, я хочу, TextBlockщоб це було Widthрівне його батьківському контейнеру Width(тобто, розтягуватись з боку на бік) або відсотку від його батьківського контейнера Width, як я можу це досягти, XAMLне вказуючи абсолютних значень?

Я хочу зробити це так, що якщо контейнер батьківського контейнера згодом буде розширений ( Widthзбільшений), його дочірні елементи також будуть автоматично розширені. (в основному, як у HTML та CSS)


Подивіться на цю відповідь .
Jesper Fyhr Knudsen

Скористайтеся відповіддю cwap і включіть tb в налаштування сітки, яке його вирівнювання розтягне.
Шиммі Вайцхандлер

Відповіді:


90

Спосіб розтягнути його на той же розмір, що і батьківський контейнер - це використовувати атрибут:

 <Textbox HorizontalAlignment="Stretch" ...

Це змусить елемент Textbox розтягуватися по горизонталі і заповнити весь батьківський простір по горизонталі (насправді це залежить від батьківської панелі, яку ви використовуєте, але повинна працювати в більшості випадків).

Відсотки можна використовувати лише зі значеннями комірок сітки, тому інший варіант - створити сітку та помістити текстове поле в одну з комірок з відповідним відсотком.


221

Ви можете помістити текстові поля всередині сітки, щоб робити відсоткові значення в рядках або стовпцях сітки, і дозволити текстові поля автоматично заповнювати їх батьківські клітини (як вони будуть за замовчуванням). Приклад:

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


7
Я вже пробував це, але отримую цю помилку: рядок '2 *' не можна перетворити на довжину. '
Андреас Греч

6
Насправді, * (Зірочка) - маленька зірка;) etymonline.com/index.php?term=asterisk
Pratik Deoghare

73
Моя мама каже, що я зірка
Denys Wessels

7
Це не працює, навіть якщо TextBox знаходиться в сітці. Ширину можна встановити на подвійний, кваліфікований подвійний (подвійне значення, за яким слідує px, в, см або pt), або автоматично. Дивіться msdn.microsoft.com/en-GB/library/…
Даррен

2
Так .. Це насправді дуже погана відповідь, але, виходячи з усіх результатів, я думаю, це допомогло комусь (було давно), тому я не видалив його.
обмін

58

Як правило, ви використовуєте вбудований елемент управління компонуванням, відповідний вашому сценарію (наприклад, використовуйте сітку як батьківську, якщо ви хочете масштабувати відносно батьківського). Якщо ви хочете зробити це з довільним батьківським елементом, ви можете створити 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>

Це дійсно круто, як я можу це зробити в коді (встановити ширину текстового поля)?
Джеремі

9
Вам слід розглянути можливість додавання CultureInfo.InvariantCultureдо подвійної конверсії, оскільки parameterце вважається як stringі в культурах з різними, decimal separatorвоно не буде працювати, як очікувалося.
Плоский Ерік

33

Для тих, хто отримує помилку типу: рядок '2 *' не може бути перетворений у Length.

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

Чому ні <RowDefinition Height="auto" />?
Бен

2
"авто" займає лише стільки місця, скільки потрібно контролю
Yama

Дякую тобі, це має бути головна відповідь.
Мафія

Це, безумовно, найкраща відповідь.
Кнут Вален

7

Можна використовувати реалізацію IValueConverter. Клас перетворювача, який приймає спадщину від IValueConverter, приймає деякі параметри, такі як value(відсоток) та parameter(батьківська ширина) та повертає потрібне значення ширини. У файлі XAML ширина компонента встановлюється з потрібним значенням:

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>

4

Я знаю, що це не 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%) і розтягується при необхідності.


4

Я використовую два способи відносного розміру. У мене є клас, який називається Relativeз трьома приєднаними властивостями To, WidthPercentі HeightPercentце корисно, якщо я хочу, щоб елемент був відносним розміром елемента в будь-якому місці візуального дерева і відчував себе менш хитким, ніж підхід перетворювача - хоча використовуйте те, що працює для вас, щоб ви задоволений.

Інший підхід є досить хитрішим. Додайте ViewBoxтуди, де ви хочете відносних розмірів всередині, потім всередині цього, додайте Gridширину 100. Потім, якщо ви додасте TextBlockширину 10 всередині, це, очевидно, 10% від 100.

ViewBoxБуде масштабувати в Gridвідповідно до будь-простором , яке було дано, так що якщо його єдине на сторінці, то Gridбуде масштабироваться повною шириною і ефективно, ваш TextBlockмасштабируются до 10% сторінки.

Якщо ви не встановите висоту, Gridто вона зменшиться, щоб відповідати її вмісту, тому всі вони будуть відносно розмірами. Вам доведеться переконатися, що вміст не надто високий, тобто починає змінювати співвідношення сторін місця, наданого ViewBoxіншому, він також почне масштабувати висоту. Ви , напевно , можете обійти це з Stretchз UniformToFill.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.