2013-04-25 2 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 в стиле или управления шаблоном, так что я могу одеяло применить его к TextBoxes, где эта ситуация применимо.

В идеальном сценарии я бы сделал что-то вроде ...

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

После просмотра этого изображения, и думать, на некоторое время, он надел на меня, что проблема заключалась в том, что даже если я прикладывал максимальную ширину в стиле правильно , свойство max width все еще применяется к корню элемента управления в 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> 

Это должно работать, но IMO, это немного странно ..

+0

Спасибо за помощь. Используя то, что вы написали, я выяснил, что именно я хотел сделать и расширил оттуда. См. Мой ответ ниже. – imdandman