WPF:如何让文本框填充所有可用的水平空间?

发布于 2025-01-16 12:49:23 字数 4716 浏览 3 评论 0原文

我正在 WPF 中创建一个表单。该表单具有文本框,其左侧带有文本块。带有 GridLines 的屏幕截图如下:

My UI

我希望它看起来像这样(原谅 MS Paint 风格): 所需 UI

问题是:文本框非常小,除非我将 Horizo​​ntalAlignment 设置为 Stretch,但如果我这样做,我无法将它们向左对齐。如何使包含 TextBlock/TextBox 的网格向左对齐使 TextBox 填充所有可用空间?

如果我对宽度进行硬编码,那么这很容易,但这显然不适用于调整大小。我尝试使用堆栈和停靠面板来固定网格,但没有成功。

我无法使用 Horizo​​ntalAlignment=Stretch、MaxWidth 和同时左对齐?因为没有其他控件是我试图填充的空间的宽度。

我也无法使用 如何在 WPF 中获取控件填充可用空间? 因为我的 xaml 中没有任何内容具有 Horizo​​ntalContentAllignment。我尝试将内容包装在 ContentControls 中并使用 ItemsControl 来强制它,但没有成功。

表单的 xaml 如下。请注意,此 xaml 适用于“创建”标题下和 3 个按钮右侧的控件。

<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <!--Left hand side content goes here-->
    <DockPanel Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
                Margin="20,0,0,0">
        <Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                <ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Input Name:"
                       HorizontalAlignment="Right" VerticalAlignment="Center"/>
            <TextBox Grid.Column="1"
                     HorizontalAlignment="Stretch" VerticalAlignment="Center"
                     Style="{StaticResource FormTextBox}"
                     Margin="5,0,5,0"/>
        </Grid>
        <Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                <ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Input Name:"
                       HorizontalAlignment="Right" VerticalAlignment="Center"/>
            <TextBox Grid.Column="1"
                     HorizontalAlignment="Stretch" VerticalAlignment="Center"
                     Style="{StaticResource FormTextBox}"
                     Margin="5,0,5,0"/>
        </Grid>
    </DockPanel>
</Grid>

FormTextBox 样式是:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox"
       x:Key="FormTextBox">
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Border CornerRadius="10"
                        Background="{StaticResource InputBrush}">
                    <Grid>
                        <Rectangle StrokeThickness="1"/>
                        <TextBox Margin="1"
                                 Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                Path=Text,
                                                Mode=TwoWay,
                                                UpdateSourceTrigger=PropertyChanged}"
                                 BorderThickness="0"
                                 Background="Transparent"
                                 VerticalContentAlignment="Center"
                                 Padding="5"
                                 Foreground="{StaticResource TextBrush}"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

它使角变圆,更改背景颜色,并删除在您通过 alt-tab 退出并返回应用程序之前选择的虚线。

I'm creating a form in WPF. The form has TextBoxes with TextBlocks to their left. A screenshot with GridLines is below:

My UI

I want it to look like this (forgive the MS Paint style):
Desired UI

The problem is: the text boxes are really small unless I set the HorizontalAlignment to Stretch, but if I do that, I can't align them to the left. How do I get the Grid containing TextBlock/TextBox to align to the left and make the TextBox fill all available space?

It's trivially easy if I hardcode widths, but that obviously won't work with resizing. I've tried playing with Stack and Dock Panels to hold the Grids with no luck.

I can't use HorizontalAlignment=Stretch, MaxWidth, and Left aligned at the same time? because there is no other control that is the width of the space I am trying to fill.

I also can't use How to get controls in WPF to fill available space? because nothing in my xaml has HorizontalContentAllignment. I tried wrapping stuff in ContentControls and using an ItemsControl to force it with no luck.

The xaml for the form is below. Note, this xaml is for the control that is under the 'Create' header and to the right of the 3 buttons.

<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <!--Left hand side content goes here-->
    <DockPanel Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
                Margin="20,0,0,0">
        <Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                <ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Input Name:"
                       HorizontalAlignment="Right" VerticalAlignment="Center"/>
            <TextBox Grid.Column="1"
                     HorizontalAlignment="Stretch" VerticalAlignment="Center"
                     Style="{StaticResource FormTextBox}"
                     Margin="5,0,5,0"/>
        </Grid>
        <Grid ShowGridLines="True" DockPanel.Dock="Top" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                <ColumnDefinition SharedSizeGroup="TextBoxColumn"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Input Name:"
                       HorizontalAlignment="Right" VerticalAlignment="Center"/>
            <TextBox Grid.Column="1"
                     HorizontalAlignment="Stretch" VerticalAlignment="Center"
                     Style="{StaticResource FormTextBox}"
                     Margin="5,0,5,0"/>
        </Grid>
    </DockPanel>
</Grid>

The FormTextBox style is:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox"
       x:Key="FormTextBox">
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Border CornerRadius="10"
                        Background="{StaticResource InputBrush}">
                    <Grid>
                        <Rectangle StrokeThickness="1"/>
                        <TextBox Margin="1"
                                 Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                Path=Text,
                                                Mode=TwoWay,
                                                UpdateSourceTrigger=PropertyChanged}"
                                 BorderThickness="0"
                                 Background="Transparent"
                                 VerticalContentAlignment="Center"
                                 Padding="5"
                                 Foreground="{StaticResource TextBrush}"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

It rounds the corners, changes the background color, and removes the dotted line that shows up if it was selected before you alt-tabbed out and back into the application.

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

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

发布评论

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

评论(1

素手挽清风 2025-01-23 12:49:24

您表明这是所需的布局:

在此处输入图像描述

您当前的代码存在一些问题。首先,使用 DockPanel 托管 TextBlock/TextBox 对,其次,没有控件设置 Grid.IsSharedSizeScope=true。您还为文本框列定义了共享大小,而实际上您只是希望它占用所有可用空间。

下面是一些实现所需布局的代码:

<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <!--Left hand side content goes here-->
    <StackPanel Orientation="Vertical" Grid.Column="1"
                Grid.RowSpan="2"
                Margin="20,0,0,0"
                Grid.IsSharedSizeScope="True" >
        <StackPanel.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Grid.Column" Value="0"/>
                <Setter Property="Text" Value="Input Name:"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
        </StackPanel.Resources>


        <Border BorderBrush="Blue" BorderThickness="5">
            <Grid ShowGridLines="True" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock/>
                <TextBox Grid.Column="1"
                         VerticalAlignment="Center" 
                         Style="{StaticResource FormTextBox}"
                         Margin="5,0,5,0"/>
            </Grid>
        </Border>
        <Border BorderBrush="Red" BorderThickness="5">
            <Grid ShowGridLines="True" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock/>
                <TextBox Grid.Column="1"
                         VerticalAlignment="Center" 
                         Style="{StaticResource FormTextBox}"
                         Margin="5,0,5,0"/>
            </Grid>
        </Border>
    </StackPanel>
</Grid>

此代码生成:

在此处输入图像描述

但实际上,如果您要获得最大可用性,您将需要为 TextBlock/TextBox 创建自己的控件,然后你可以将其放入某种动态内容的 ItemsControl 中。

You indicate that this is the desired layout:

enter image description here

There are a few problems with your current code. First, using a DockPanel to host the TextBlock/TextBox pairs, and second, no control has Grid.IsSharedSizeScope=true set on it. You also have defined a shared size for the text box column when in reality you just want it to take up all the available space.

Here is some code that achieves the desired layout:

<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <!--Left hand side content goes here-->
    <StackPanel Orientation="Vertical" Grid.Column="1"
                Grid.RowSpan="2"
                Margin="20,0,0,0"
                Grid.IsSharedSizeScope="True" >
        <StackPanel.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Grid.Column" Value="0"/>
                <Setter Property="Text" Value="Input Name:"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
        </StackPanel.Resources>


        <Border BorderBrush="Blue" BorderThickness="5">
            <Grid ShowGridLines="True" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock/>
                <TextBox Grid.Column="1"
                         VerticalAlignment="Center" 
                         Style="{StaticResource FormTextBox}"
                         Margin="5,0,5,0"/>
            </Grid>
        </Border>
        <Border BorderBrush="Red" BorderThickness="5">
            <Grid ShowGridLines="True" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="TextBlockColumn"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock/>
                <TextBox Grid.Column="1"
                         VerticalAlignment="Center" 
                         Style="{StaticResource FormTextBox}"
                         Margin="5,0,5,0"/>
            </Grid>
        </Border>
    </StackPanel>
</Grid>

This code produces:

enter image description here

In reality though, if you're going for maximum usability, you'll want to create your own control for the TextBlock/TextBox, and then you could just put it in an ItemsControl of some kind for dynamic content.

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