如何应用文本框控件模板? [英] How to apply TextBox Control Template?

查看:82
本文介绍了如何应用文本框控件模板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试简化一些代码并提高我的可维护性。

I'm trying to simplify some code and improve my maintainability.

我最初是在寻找一种使文本框向左对齐的方法,该文本框可以缩小和扩展到最大值,而在达到最大值后不居中于网格单元内值。

I was initially seeking a way to have a text box aligned to the left, that can shrink and expand to a maximum value without centering inside a grid cell after reaching the maximum value.

所以我开始写这样的代码...

So I started out writing some code like this...

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <TextBox Text="Some text"
             VerticalAlignment="Center"
             HorizontalAlignment="Stretch"
             Margin="10"
             MaxWidth="150" />
</Grid>

(代码清单1)

这会产生类似以下内容……

And that yields something looking like this...

(图1)

如您所见,这使TextBox的最大宽度居中,但它在网格单元的中心对齐。

As you can see, this centers the TextBox with it's max width, but it is aligned in the center of the grid cell.

所以我也许像这样更改了文本框的水平对齐方式。

So then I though maybe if i changed the horizontal alignment of the text box like so...

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <TextBox  Text="Some text"
              VerticalAlignment="Center"
              HorizontalAlignment="Left"
              Margin="10"
              MaxWidth="100" />
</Grid>

(代码清单2)

但是不幸的是,这只会产生如下所示的东西...

But unfortunately, that only yields something looking like this...

(图2)

同样,这是不对的,因为尽管右侧有所有空白区域,但文本框并没有像我想要的那样扩展到最大宽度100。

Again, this isn't right because, despite all the empty space on the right, the text box is not expanding to its max width of 100 like I want.

最终,我发现,如果将TextBox放在嵌套的网格中,则会达到预期的效果。

Eventually, I found that if put the TextBox inside a nested grid, you will achieve the desired effect.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"
                              MaxWidth="120" />
            <ColumnDefinition Width="0*" />
        </Grid.ColumnDefinitions>
        <TextBox Text="Some text"
             VerticalAlignment="Center"
             HorizontalAlignment="Stretch"
             Margin="10"
             MaxWidth="100" />
    </Grid>
</Grid>

(代码清单3)

哪个会产生这个...

Which yields this...

(图3)

看到,嵌套的网格填充了整个200宽的空间,但是文本框填充了左侧的100,而右侧保留了空白空间。 (如果此窗口可调整大小,它将适当缩小和扩展)。

As you can see, the nested grid fills the entire 200 wide space, but the text box fills the left 100, and leaves the empty space on the right. (If this window is re-sizable it will shrink and expand appropriately)

我想将代码清单3 的方法应用于样式或控件模板,因此我可以将其应用于适用于这种情况的TextBoxes。

I would like to apply the methods of Code Listing 3 to a style or control template, so I can blanket apply it to TextBoxes where this situation is applicable.

在理想情况下,我会做类似...

In a perfect scenario, I would do something like...

<TextBox Text="Some text"
         VerticalAlignment="Center"
         HorizontalAlignment="Stretch"
         Margin="10"
         MaxWidth="100"
         Style="{StaticResource ExpandingTextBox}" /> 

(代码清单4)

并获得与图3 相同的结果。

我尝试了以下操作...

I tried the following...

<Style TargetType="{x:Type TextBox}"
       x:Key="ExpandingTextBox">
    <Setter Property="OverridesDefaultStyle"
            Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"
                                          MaxWidth="170" />
                        <ColumnDefinition Width="0*" />
                    </Grid.ColumnDefinitions>
                    <ContentPresenter/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

(代码清单5)

但是,这只会导致文本框从我的表单中一起消失。我不太擅长编写这样的模板,所以我有点茫然。

But that just causes the text box to disappear from my form all together. I'm not very good at writing templates like this, so I'm kind of at a loss.

此外,我刚刚意识到的一件事是嵌套列= MaxWidth + 2 x边距。我不介意在TextBox声明中显式设置列宽,但是如果可以自动设置,那真是太棒了。

Also, one thing I just realized is that the width of the nested column = MaxWidth + 2 x Margin. I wouldn't mind setting the column width explicitly in the TextBox declaration, but if it could be automatic, that would be awesome.

推荐答案

感谢 jure 让我入门。与往常一样,事实证明,该解决方案比它最初允许的要复杂得多。

Thanks to jure for getting me started. As always, it turns out that the solution is a bit more convoluted than it originally lets on.

让我们检查一下我做了什么。

Let's examine what I did.

使用上一篇文章中提出的想法,并进行一些修改之后,我想到了以下代码。

Using the ideas presented in the previous post, and after a bit of finagling, I came up with the following code.

<Style TargetType="{x:Type TextBox}"
       x:Key="ExpandingTextBox">
    <Setter Property="OverridesDefaultStyle"
            Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*">
                            <ColumnDefinition.MaxWidth>
                                <Binding Path="MaxWidth"
                                         RelativeSource="{RelativeSource TemplatedParent}">
                                </Binding>
                            </ColumnDefinition.MaxWidth>
                        </ColumnDefinition>
                        <ColumnDefinition Width="0*" />
                    </Grid.ColumnDefinitions>
                    <TextBox  Text="{TemplateBinding Text}">
                        <TextBox.MaxWidth>
                            <Binding Path="MaxWidth"
                                     RelativeSource="{RelativeSource TemplatedParent}" />
                        </TextBox.MaxWidth>
                    </TextBox>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

(代码清单6)

当然也可以在我的页面的XAML标记中应用它...

And of course applied it in the XAML markup for my page like this...

<TextBox  Grid.Column="1"
          Grid.Row="3"
          Text="{Binding Path=Username}"
          Style="{StaticResource ExpandingTextBox}"
          Margin="10"
          MaxWidth="200" />

(代码清单7)

给出这样的结果...

That gives a result like this...

(图4)

在查看了该图像并思考了一段时间之后,它使我感到困惑,问题是,即使我正确地在样式内应用了最大宽度,但最大宽度属性仍被应用于XAML中控件的根。

After looking at that image, and thinking for a while, it donned on me that the problem was that even though I was applying the max width inside the style correctly, the max width property was still being applied to the root of the control in XAML.

本质上是将其压缩到页面上的最大宽度,然后完成此操作,它根据样式应用了最大宽度!

Essentially it was squeezing it down to the max width on the page, and then after that was done, it applied the max width pursuant to the styling!

如此简单,却难以捉摸!

So simple, but so elusive!

因此,我修改了样式以使用Tag属性来应用样式化的最大宽度元素,因为Tag属性在根目录不做任何事情。

Therefore, I modified the style to use the Tag property to apply to the styled max width elements, since the Tag property doesn't do anything at the root.

<Style TargetType="{x:Type TextBox}"
       x:Key="ExpandingTextBoxMaxWidthInTag">
    <Setter Property="OverridesDefaultStyle"
            Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*">
                            <ColumnDefinition.MaxWidth>
                                <Binding Path="Tag"
                                         RelativeSource="{RelativeSource TemplatedParent}">
                                </Binding>
                            </ColumnDefinition.MaxWidth>
                        </ColumnDefinition>
                        <ColumnDefinition Width="0*" />
                    </Grid.ColumnDefinitions>
                    <TextBox  Text="{TemplateBinding Text}">
                        <TextBox.MaxWidth>
                            <Binding Path="Tag"
                                     RelativeSource="{RelativeSource TemplatedParent}" />
                        </TextBox.MaxWidth>
                    </TextBox>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

(代码清单8)

像这样在XAML中应用的...

Which is applied in XAML like this...

<TextBox  Grid.Column="1"
          Grid.Row="3"
          Text="{Binding Path=Username}"
          Style="{StaticResource ExpandingTextBoxMaxWidthInTag}"
          Margin="10"
          Tag="200" />

最后 给出了所需的结果...

And finally gives the desired results like this...

(图5)

(图6)

所以,真正的窍门是意识到我并不一定要限制整个模板控件的最大宽度,而只是想限制控件内部的TextBox的宽度!

So, the real trick was realizing that I didn't necessarily want to limit the max width of the entire templated control, but instead just wanted to limit the width of the TextBox internal to the control!

一旦我弄清楚了,只使用Tag属性是有意义的,该属性在根级别没有任何作用!

Once I figured that out, it only made sense to use the Tag property which wasn't doing anything to the control at the root level!

我希望这对可能遇到此问题的其他人有所帮助!

I hope this helps anyone else who might have this problem!

这篇关于如何应用文本框控件模板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆