如何以这种方式调整WPF Grid面板的大小?

时间:2012-01-25 10:55:45

标签: c# .net wpf xaml grid-layout

我有一个非常简单的窗口,其中一个Grid包含两列,一个TextBlock和一个TextBox。

enter image description here

我需要将第0列设置为自动调整其内容大小,并使第1列(内容)为第0列大小的4倍。

我该怎么做?如果这是解决方案,我将创建一个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的一个好处是它无法在没有固定尺寸的情况下工作吗?如果你有缺陷并且你有更大的字体大小,一切都会好看。如果您将UI翻译成另一种需要x2大小的语言,一切都会好起来的。如果你有不同的PPI设置,一切都会好起来的。

但我不想看到的是屏幕在运行时改变其大小,因为用户不习惯这样做。这就是为什么我想将输入字段的大小设置为知道字段的倍数的原因。如果我让标签单元格重新调整到需要的大小,然后我将内容单元格设置为标签的乘数,我将获得自动调整的好处,以及用户期望具有固定大小屏幕的行为(除非他们更改调整大小它)。

4 个答案:

答案 0 :(得分:6)

您可以在网格列上使用绑定:

<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();
    }
}

您也可以为网格列编写附加属性。

答案 1 :(得分:0)

取自: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布局被设计为保护性的,即如果你的网格的孩子不能缩小 - 通常你的布局逻辑应该适应它,通常是通过暂停一些布局规则。

答案 2 :(得分:0)

修改

如果在编译时已知大小,手动设置宽度会不会更容易?


你可以使用BindingConverter,我会在水平StackPanel中使用单独的项目(看看StackPanel的宽度对于你的内容来说足够大):

这是清理后的代码。

MainWindow.xaml:

<!-- 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();
    }
}

答案 3 :(得分:0)

据我所知,您正在尝试布局标签(文本块)及其相应的输入字段。作为一个指标,你应该首先看到Beth Massi's Windows Client video关于开发data entry表单的简单数据输入表格,但是也很好地展示了布局。

特别注意她如何使用设计器,属性窗口和XAML来设置WPF窗口上的控件,然后我认为您不应该需要第一列为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> 属性:

    .Xaml.cs
  2. 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(); } } } 文件代码(请注意转换器):

    {{1}}