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

发布于 2024-12-28 18:21:54 字数 1449 浏览 3 评论 0原文

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

在此处输入图像描述

我需要什么来将第 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 设置,一切都会看起来很好。

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

I have this pretty simple window with a Grid containing two columns, a TextBlock and a TextBox.

enter image description here

What I need it to set the column 0 to automatically size to its content and to have column 1 (content) to be 4 times the size of the column 0.

How can I do that. I will create a Grid descendant if this is the solution because I really need this feature.

Edit: more explanations. The content of the column 0 won't change at runtime so the size of the column 0 or column 1 must not change on runtime. The grid will be the child of a window configured with SizeToContent="WidthAndHeight" so no extra space must exist.

Answer to Dmitry: I tried what you say with the following code and it is not working at all:

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

Last Edit: Why the hell do I (or anyone) need this?

One of the nice things of WPF is its hability to work without fixed sizes right? If you are impaired and you have a bigger font size everything will look fine. If you translate your UI to another language that needs x2 size everything will look fine. If you have different PPI settings everything will look fine.

But what I don't want to see is screens changing its size at runtime because users are not used to this. That's why I want to set the size of the entry fields to a multiple of a know field. If I let the label cell to re size to what it needs and then I set the content cell to a multiplier of the label I will get the benefits of autosizing with the behaviour that users expect of having fixed size screens (unless they change it resizing it).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夢归不見 2025-01-04 18:21:54

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

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

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

You can use bindings on grid columns:

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

Then the converter:

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

You could write an attached property for grid columns also.

棒棒糖 2025-01-04 18:21:54

编辑:

如果尺寸在编译时已知,那么手动设置宽度不是更容易吗?


您可以为此使用 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();
    }
}

Edit:

If the sizes are known at compile time, wouldn't it be easier to set the widths manually?


You could use a BindingConverter for that, I'd go with separate items in a horizontal StackPanel (look that the StackPanel's width is big enough for your contents):

Here's the cleaned code.

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();
    }
}
陌伤ぢ 2025-01-04 18:21:54

摘自: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 布局被设计为具有保护性,即如果您的网格的子级无法缩小 - 通常您的布局逻辑应该适应它,通常是通过暂停某些布局规则。

Taken from: http://www.tanguay.info/web/index.php?pg=codeExamples&id=36

the idea is to use:

Update 2 - full XAML posted (mind the behavior of your grid's children):

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

I've just checked it and it worked.

Update: Simply put - there's no out of the box way for doing this in WPF. Depending on your circumstanes you'll have to come up with some sort of a trick to get your grid working.

Another problem is - in general WPF layouts are designed to be protective, i.e. if your grid's child cannot be shrinked down - normally your layout logic should accomodate for it, typically by suspending some layout rules.

一曲爱恨情仇 2025-01-04 18:21:54

据我了解,您正在尝试布局标签(文本块)及其相应的输入字段。作为指标,您应该首先查看 Beth Massi 的 关于简单数据输入表单的 Windows 客户端 视频,该视频介绍了如何开发数据输入 表单,但布局也得到了很好的演示。

特别是观察她如何使用设计器、属性窗口和 XAML 在 WPF 窗口上布置控件,然后我认为您不需要将第一列设置为 Auto< /code> 大小和 4* 第一列的第二列。

编辑:根据相关更新,我发布了一个可能的解决方案,如下所示:

  1. XAML 文件代码(请注意 Window 中的 SizeToContent 用法> 并且绑定到 Textbox 控件的 ActualWidth 属性):

    
    <网格>
        <网格.资源>
            >
        
        
            
            
        
        <文本块名称=“tb”
                   网格列=“0”
                   Text="自动文本,在设计时更改以查看宽度的变化" />
        <文本框名称=“tx”
                 网格列=“1”
                 宽度=“{绑定元素名称=tb,
                                 路径=实际宽度,
                                 转换器={StaticResource FourWidthConv}}"
                 Text="4 * col 1 宽度在 SizetoContentWindow 中显示文本" />
    
    
    
  2. .Xaml.cs 文件代码(注意此处的转换器):

    使用 System.Windows;
    使用 System.Windows.Data;
    
    命名空间 GridTest
    {
        /// <摘要>
        /// MainWindow.xaml 的交互逻辑
        /// 
        公共部分类 MainWindow : 窗口
        {
            公共主窗口()
            {
                初始化组件();
            }
        }
    
        公共类 FourWidthConverter :IValueConverter
        {
            公共对象转换(对象值,System.Type targetType,对象参数,System.Globalization.CultureInfo文化)
            {
                返回 4 *(双精度)值;
            }
    
            公共对象 ConvertBack(对象值,System.Type targetType,对象参数,System.Globalization.CultureInfo 文化)
            {
                抛出新的 System.NotImplementedException();
            }
        }
    }
    

As I understand you are trying to layout the label (textblock) and the corresponding entry field for it. As an indicator, you should first see the Beth Massi's Windows Client video on simple data entry form which is on developing a data entry form but laying out is also demonstrated very well.

Particularly observe how she lays out the controls on the WPF Window using the designer, properties window and XAML, and then I think you should not have a need for the first column to be of Auto size and second column of 4* first column.

EDIT: As per update in question, I am posting a possible solution as below:

  1. XAML file code (Notice the SizeToContent usage in Window and that the binding is to ActualWidth property for Textbox control):

    <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 file code (Notice the converter here):

    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();
            }
        }
    }
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文