2013-04-25 58 views
3

我试图简化一些代码并提高可维护性。如何应用TextBox控件模板?

我最初正在寻找一种方法来让文本框左对齐,即可以缩小并展开到最大值,而不会在达到最大值后在网格单元格内居中。

于是我开始写一些像这样的代码...

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

(代码1)

而且能产生一些看起来像这样...

TextBox in Grid Centered

(图1)

正如您所看到的,这使TextBox以其最大宽度为中心,但它在网格单元的中心对齐。

于是我虽然也许如果我改变,像这样的文本框中的水平对齐方式...

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

(代码2)

但不幸的是,这仅产生看东西像这样...

Too small TextBox left aligned

(FIGUR e 2)

同样,这是不正确的,因为尽管所有在右侧的空白空间,文本框并没有扩大到我想要的最大宽度100。

最后,我发现如果将TextBox放入嵌套网格中,您将获得所需的效果。

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

其中产量这...

Correct looking TextBox

(图3)

正如你所看到的,嵌套网格填充整个200宽的空间,但文本框填充左边10 0,并留下右侧的空白空间。 (如果重新可观的窗口就会缩小,适当扩大)

我想的代码3方法适用于样式或控件模板,这样我就可以毯子将其应用到文本框,其中这种情况适用。

在一个完美的场景中,我会做类似......

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

(代码4)

而达到相同的结果图3

我尝试以下...

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

但是,这只是使文本框从我的形式消失一起。我不擅长编写这样的模板,所以我有点不知所措。

另外,我刚刚意识到的一件事是嵌套列的宽度= MaxWidth + 2 x Margin。我不介意在TextBox声明中明确地设置列宽,但如果它可以是自动的,那就太棒了。

回答

3

感谢jure你为我开始。与往常一样,事实证明,解决方案比最初的解决方案要复杂得多。

让我们来看看我做了什么。

使用上一篇文章中介绍的思路,经过一番讨论后,我想出了下面的代码。

<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标记为我的网页这样的应用它,并...

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

(代码7)

给出这样的结果...

Incorrect Style Template

(图4)

看着这个形象,并思考了一会儿后,穿上了我的问题是,即使我正确地应用最大宽度的样式里面,最大宽度属性仍然应用于XAML中控件的根目录。

本质上它是挤压到页面上的最大宽度,然后完成后,根据造型应用最大宽度!

太简单了,但太难以捉摸!

因此,我修改了样式以使用Tag属性应用于样式化的最大宽度元素,因为Tag属性不会在根部执行任何操作。

<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像这样的应用...

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

而且最后给出这样的...

所期望的结果

Desired Result with Layout Shown

(图5)

Desired Result without Layout Shown

(图6)

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

一旦我明白了这一点,只有使用Tag属性才能对根级别的控件做任何事情!

我希望这可以帮助任何其他人可能有这个问题!

7

您需要一个TextBox而不是ContentPresenter在您的模板中。您将TextBox的默认模板替换为不再具有文本输入区域的模板。 尝试这样的:

<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> 
         <TextBox Text="{TemplateBinding Text}" 
            VerticalAlignment="Center" 
            HorizontalAlignment="Stretch" 
            Margin="10" 
            MaxWidth="100" 
         /> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

这应该工作,但海事组织,有点怪异..

+0

感谢您的帮助。用你写的东西,我确切地想出了我想要做什么并从那里扩展。请参阅下面的答案。 – imdandman 2013-04-26 16:12:23