Как подобрать размер панели WPF Grid? - PullRequest
3 голосов
/ 25 января 2012

У меня есть это довольно простое окно с сеткой, содержащей два столбца, TextBlock и TextBox.

enter image description here

Что мне нужно, чтобы задать для столбца 0 автоматический размер его содержимого и чтобы столбец 1 (содержимое) в 4 раза превышал размер столбца 0.

Как я могу это сделать. Я создам потомок Grid, если это решение, потому что мне действительно нужна эта функция.

Редактировать: больше объяснений. Содержимое столбца 0 не изменится во время выполнения, поэтому размер столбца 0 или столбца 1 не должен изменяться во время выполнения. Сетка будет дочерней по отношению к окну, сконфигурированному с SizeToContent="WidthAndHeight", поэтому дополнительное пространство не должно существовать.

Ответ Дмитрию : Я попробовал то, что вы говорите, с помощью следующего кода, и он вообще не работает:

<Window x:Class="UnderstandSizing.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" 
SizeToContent="WidthAndHeight" >
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".25*" />
        <ColumnDefinition Width=".75*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Column="0" Text="THIS IS THE LABEL:" />
    <TextBox Grid.Column="1" Text="content" />
</Grid>
</Window>

Последнее редактирование: какого черта мне (или кому-либо еще) это нужно?

Одна из приятных сторон WPF - его способность работать без фиксированных размеров, верно? Если у вас проблемы с шрифтом большего размера, все будет хорошо. Если вы переведете свой пользовательский интерфейс на другой язык, который нуждается в размере x2, все будет хорошо выглядеть. Если у вас разные настройки PPI, все будет хорошо.

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

Ответы [ 4 ]

6 голосов
/ 25 января 2012

Вы можете использовать привязки к столбцам сетки:

<Grid.ColumnDefinitions>
   <ColmunDefinition Width="Auto" x:Name="firstCol"/>
   <ColumnDefinition Width="{Binding ActualWidth, ElementName=firstCol, Converter={StaticResource MultiplyConverter}, ConverterParameter=4}" />
</Grid.ColumnDefinitions>

Затем преобразователь:

public class MultiplyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double originalValue;
        double multiplier;
        if (value != null && parameter != null && 
            double.TryParse(value.ToString(), out originalValue) &&
            double.TryParse(parameter.ToString(), out multiplier)) //Can be lots of things: sentinel object, NaN (not a number)...
        {
            return originalValue * multiplier;
        }
        else return Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Вы также можете написать присоединенное свойство для столбцов сетки.

0 голосов
/ 25 января 2012

Как я понимаю, вы пытаетесь расположить метку (текстовый блок) и соответствующее поле ввода для нее. В качестве индикатора вы должны сначала увидеть Beth Massi's Windows Client видео в простой форме ввода данных, которая находится на стадии разработки формы data entry, но ее раскладка также продемонстрирована очень хорошо.

Особенно понаблюдайте, как она размещает элементы управления в окне WPF, используя конструктор, окно свойств и XAML, и тогда я думаю, что вам не нужно иметь размер первого столбца Auto и второго столбца. 4* первый столбец.

РЕДАКТИРОВАТЬ: В соответствии с обновлением, я публикую возможное решение, как показано ниже:

  1. Код файла XAML (обратите внимание на использование SizeToContent в Window и что привязка к свойству ActualWidth для элемента управления Textbox):

    <Window x:Class="GridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:GridTest"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        d:DesignHeight="350"
        d:DesignWidth="525"
        SizeToContent="WidthAndHeight"
        mc:Ignorable="d">
    <Grid>
        <Grid.Resources>
            <local:FourWidthConverter x:Key="FourWidthConv" />
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Name="tb"
                   Grid.Column="0"
                   Text="Auto Text, change at design time to see changes in Width" />
        <TextBox Name="tx"
                 Grid.Column="1"
                 Width="{Binding ElementName=tb,
                                 Path=ActualWidth,
                                 Converter={StaticResource FourWidthConv}}"
                 Text="4 * col 1 width displaying Text in SizetoContentWindow" />
    </Grid>
    </Window>
    
  2. .Xaml.cs код файла (обратите внимание на конвертер здесь):

    using System.Windows;
    using System.Windows.Data;
    
    namespace GridTest
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    
        public class FourWidthConverter : IValueConverter
        {
            public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return 4 * (double)value;
            }
    
            public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new System.NotImplementedException();
            }
        }
    }
    
0 голосов
/ 25 января 2012

Редактировать:

Если размеры известны во время компиляции, не проще ли установить ширину вручную?


Вы можете использоватьBindingConverter для этого, я бы пошел с отдельными элементами в горизонтальной StackPanel (посмотрите, что ширина StackPanel достаточно велика для вашего содержимого):

Вот очищенный код.:

<!-- define xmlns:local="clr-namespace:YourAppNamespace" -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
    <StackPanel.Resources>
        <local:WidthConverter x:Key="wc" />
    </StackPanel.Resources>
    <Grid Background="Gray" x:Name="col1">
        <TextBlock Text="blub"/>
    </Grid>
    <Grid Background="Orange" Width="{Binding ElementName=col1, Path=ActualWidth, Converter={StaticResource ResourceKey=wc}}">
        <Label Content="bla"></Label>
    </Grid>
</StackPanel>

MainWindow.xaml.cs:

public class WidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is double))
        {
            return Binding.DoNothing;
        }
        return ((double)value) * 4.0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
0 голосов
/ 25 января 2012

Взято из: http://www.tanguay.info/web/index.php?pg=codeExamples&id=36

Идея состоит в том, чтобы использовать:

Обновление 2 - опубликован полный XAML (обратите внимание на поведение детей вашей сетки):

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width=".25*" />
                <ColumnDefinition Width=".75*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid Background="Yellow" Grid.Column="0">
                <TextBlock  Text="THIS IS THE LABEL:" />
            </Grid>
            <Grid Background="Blue" Grid.Column="1">
                <TextBox Background="Transparent" Text="content" />
            </Grid>

        </Grid>

    </Grid>
</Window>

Я только что проверил, и это сработало.

Обновление: Проще говоря - нет готового способа сделать это в WPF.В зависимости от ваших обстоятельств вам придется придумать какой-то прием, чтобы ваша сетка работала.

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

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