2013-05-07 17 views
6

TextBoxに、2つの境界線をパディングして再テンプレートしようとしています。しかし、PART_ ContentHostのパディングを明示的にゼロに設定しても、コントロールのパディングは常に内側のScrollViewerにも適用されます。TextBoxテンプレートパディングの問題

小さな例:私は期待しながら15 [15 テキストフィールド 15] 15]

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TextBox}"> 
       <Border Padding="{TemplateBinding Padding}" 
         BorderThickness="1" 
         BorderBrush="Black" 
         Background="LightBlue"> 
        <ScrollViewer Padding="0" Margin="0" Background="Turquoise" 
            x:Name="PART_ContentHost" /> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

<TextBox Padding="15"/> 

結果がどのように見えるテキストボックスである[15 [テキストフィールド] 15]

PART_ContentHost(スクロールビューア/テキストフィールド)にゼロ埋め込みを強制するにはどうすればよいですか?

答えて

6

これは本当に誰かがこの動作についてより良い説明をしていない限り、私には奇妙なバグのように見えます。

ScrollViewer(PART_ContentHost)は、内部のようなTemplateを使用しています:面白いビットが

<ControlTemplate TargetType="{x:Type ScrollViewer}"> 
    <Grid x:Name="Grid" 
     Background="{TemplateBinding Background}"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Rectangle x:Name="Corner" 
       Grid.Row="1" 
       Grid.Column="1" 
       Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" /> 
    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" 
          Grid.Row="0" 
          Grid.Column="0" 
          Margin="{TemplateBinding Padding}" 
          CanContentScroll="{TemplateBinding CanContentScroll}" 
          CanHorizontallyScroll="False" 
          CanVerticallyScroll="False" 
          Content="{TemplateBinding Content}" 
          ContentTemplate="{TemplateBinding ContentTemplate}" /> 
    <ScrollBar x:Name="PART_VerticalScrollBar" 
       Grid.Row="0" 
       Grid.Column="1" 
       AutomationProperties.AutomationId="VerticalScrollBar" 
       Cursor="Arrow" 
       Maximum="{TemplateBinding ScrollableHeight}" 
       Minimum="0" 
       ViewportSize="{TemplateBinding ViewportHeight}" 
       Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" 
       Value="{Binding VerticalOffset, 
           Mode=OneWay, 
           RelativeSource={RelativeSource TemplatedParent}}" /> 
    <ScrollBar x:Name="PART_HorizontalScrollBar" 
       Grid.Row="1" 
       Grid.Column="0" 
       AutomationProperties.AutomationId="HorizontalScrollBar" 
       Cursor="Arrow" 
       Maximum="{TemplateBinding ScrollableWidth}" 
       Minimum="0" 
       Orientation="Horizontal" 
       ViewportSize="{TemplateBinding ViewportWidth}" 
       Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" 
       Value="{Binding HorizontalOffset, 
           Mode=OneWay, 
           RelativeSource={RelativeSource TemplatedParent}}" /> 
    </Grid> 
</ControlTemplate> 

:今

<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" 
         Grid.Row="0" 
         Grid.Column="0" 
         Margin="{TemplateBinding Padding}" 
         CanContentScroll="{TemplateBinding CanContentScroll}" 
         CanHorizontallyScroll="False" 
         CanVerticallyScroll="False" 
         Content="{TemplateBinding Content}" 
         ContentTemplate="{TemplateBinding ContentTemplate}" /> 

0にあなたがちょうどそこにマージンを設定することができ、あなたの問題を解決する代わりに、 {TemplateBinding Padding}あなたはあなたの希望する出力を得るでしょう。

しかし、なぜそれを行う必要がありましたか?

TemplateBinding Paddingは、[OK]をそれは奇妙だが、何より悪いのですがある内側の範囲にあり、15

である親(Button)から継承されたパディング値を選ぶScrollViewer上で直接設定された値を無視しているように見えますそれはパディングのためだけです。 Foreground,Background,Marginは、ScrollViewerに直接設定するとすべて問題なく、TextBoxのフィールドより優先されます。私はさらに、Paddingをデフォルトのスタイル設定ツールTextBoxに直接セットして、いくつかの優先順位のケースが問題かどうかを確認しました。

そうではありませんでした。同じ出力を得ました。

パディングはSystem.Windows.Controls.Controlで定義されています。これは同じクラスのフォアグラウンドで、背景はScrollViewerから継承しています。なぜパディングのみが異なる動作をしているのか分かりません。

私も

<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" 
         Grid.Row="0" 
         Grid.Column="0" 
         Margin="{TemplateBinding Margin}" 
         CanContentScroll="{TemplateBinding CanContentScroll}" 
         CanHorizontallyScroll="False" 
         CanVerticallyScroll="False" 
         Content="{TemplateBinding Padding}" 
         ContentTemplate="{TemplateBinding ContentTemplate}" /> 

また、印刷の15,15,15,15のようなものにプレゼンターを変更してみました。 Marginの場合は実行しません。

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}, Path=Padding}結合と同じ効果。

ScrollViewerは、子にそれに設定されたプロパティを渡さないという1つの投稿を見ました。それが実際の場合は、BackgroundMargin、どのようにオーバーライドしたのですか?何が特別なPaddingについての特別な?それが有効な振る舞いであれば、テンプレートなしでその振る舞いを取り除く方法は実際にはわかりません。これは、複雑な実装の1つで、ScrollViewerです。

+0

詳細とよくテストされた回答をいただきありがとうございます!私はscrollviewerテンプレートに関する情報と情報を本当に感謝しています。これは確かに奇妙なケースですが、それは私にはあまり意味がありません。 –

3

この奇妙な振る舞いはTextBoxBaseです。 それはそれのいくつかのメタデータを上書きしますが、依存関係プロパティのだとPaddingプロパティのためには、次のようになります。あなたはOnScrollViewerPropertyChangedハンドラの表情を取る場合は、ScrollViewerのだと

Control.PaddingProperty.OverrideMetadata(
    typeof (TextBoxBase), 
    new FrameworkPropertyMetadata(
     new PropertyChangedCallback(TextBoxBase.OnScrollViewerPropertyChanged))); 

は、あなたはそれが変更されたプロパティの値を渡すことがわかります:

コントロールテンプレートでどのような値を設定しても、実行時にTextBoxによってローカル値で上書きされます。

InvertThicknessConverterが渡された厚さの値のすべてのコンポーネントを否定値コンバータ、ある
<ScrollViewer 
    x:Name="PART_ContentHost" 
    Margin="{TemplateBinding Padding, Converter={StaticResource InvertThicknessConverter}}" 
/> 

public class InvertThicknessConverter: IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is Thickness) return InvertThickness((Thickness)value); 
     return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is Thickness) return InvertThickness((Thickness)value); 
     return value; 
    } 

    private static Thickness InvertThickness(Thickness value) 
    { 
     return new Thickness(-value.Left, -value.Top, -value.Right, -value.Bottom); 
    } 
} 
+0

興味深い発見!詳細をありがとう。問題を回避するためにカスタムのスクロールビューアースタイルを引き続き使用する予定ですが、オプションを用意して問題の原因を理解することは素晴らしいことです。 –

+0

実際には、コンバーターを使用していてControlTemplateをオーバーライドしているだけなので、これは受け入れられた答えよりも優れています。私の場合、 'ScrollViewer'の' Padding'、_not_ 'Margin'にバインドした場合にのみ動作します。 –

0

私はに走ったのテンプレートにScrollViewerのに負のマージンを設定することができ、このパディングを補償する

この問題は、DataGridColumnHeaderPaddingプロパティを設定したときに、パディングプロパティを0に近づけないように指定して回避しました。

<Style x:Key="CustomHeader" TargetType="DataGridColumnHeader" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}"> 
    <!-- Why you might ask do we need a value that is near but not actually 0? No idea, but if it is not there, "4" is used. --> 
    <!-- See http://stackoverflow.com/questions/16424739/textbox-template-padding-issue --> 
    <Setter Property="Padding" Value="0,0,0.000000000001,0" /> 
</Style> 
関連する問題