2013-04-25 50 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