2013-05-07 7 views
6

मैं TextBox को दो-सीमाओं के बीच पैडिंग के साथ दोबारा टेम्प्लेट करने का प्रयास कर रहा हूं; हालांकि, जब भी मैं स्पष्ट रूप से PART_ing ContentHost शून्य पर पैडिंग सेट करता हूं, तब भी नियंत्रण के लिए पैडिंग हमेशा आंतरिक ScrollViewer पर लागू होती है।टेक्स्टबॉक्स टेम्पलेट पैडिंग समस्या

छोटे उदाहरण: [15 [15 Textfield 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 [Textfield] 15]

शून्य पैडिंग रखने के लिए मैं PART_ContentHost (scrollviewer/textfield) को सही तरीके से कैसे बल दूं?

उत्तर

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 PaddingScrollViewer जो आंतरिक दायरे में है और जनक से विरासत में मिली पैडिंग मूल्य उठाता पर सीधे सेट मूल्य अनदेखी किए जाने (Button) जो 15

ठीक है कि अजीब है, लेकिन क्या बदतर है है लगता है यह केवल पैडिंग के लिए है। Foreground, Background, MarginScrollViewer पर सीधे सेट होने पर ठीक है, वे 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 इसके बच्चों के लिए निर्धारित गुणों को पास नहीं करता है।वास्तव में ऐसा नहीं मिलता है क्योंकि अगर ऐसा होता है तो Background, Margin और किस तरह से सवारी करने के लिए ठीक हो? Padding के बारे में इतना खास क्या है? यदि यह वैध व्यवहार है, तो मैं वास्तव में ScrollViewer को टेम्पलेट किए बिना उस व्यवहार से छुटकारा पाने के लिए नहीं देखता हूं और यह एक भ्रमित कार्यान्वयन है।

+0

विस्तृत और अच्छी तरह से परीक्षण किए गए उत्तर के लिए आपको बहुत बहुत धन्यवाद! मैं स्क्रॉलव्यूज़र टेम्पलेट के बारे में इनपुट और जानकारी की वास्तव में सराहना करता हूं। यह निश्चित रूप से एक अजीब मामला है, जो मुझे ज्यादा समझ में नहीं आता है। –

3

यह अजीब व्यवहार TextBoxBase से आ रहा है। यह इसके बारे में कुछ के लिए मेटाडाटा को ओवरराइड करता है निर्भरता गुण है और Padding संपत्ति के लिए यह दिखाई देता है:

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

आप OnScrollViewerPropertyChanged हैंडलर पर एक नज़र डालें तो आप देखेंगे कि यह बदली हुई संपत्ति के मूल्य से गुजरता यह ScrollViewer है करने के लिए:

if (newValue == DependencyProperty.UnsetValue) 
    textBoxBase.ScrollViewer.ClearValue(e.Property); 
    else 
    textBoxBase.ScrollViewer.SetValue(e.Property, newValue); 

तो, कोई बात नहीं क्या पैडिंग मूल्य आप नियंत्रण टेम्पलेट में सेट करते हैं, यह क्रम में पाठ बॉक्स द्वारा स्थानीय मूल्य के साथ ओवरराइट किया जाएगा।

इस गद्दी आप टेम्पलेट में ScrollViewer के लिए नकारात्मक मार्जिन सेट कर सकते हैं क्षतिपूर्ति करने के लिए:

<ScrollViewer 
    x:Name="PART_ContentHost" 
    Margin="{TemplateBinding Padding, Converter={StaticResource InvertThicknessConverter}}" 
/> 

जहां 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

यह स्वीकार्य उत्तर से वास्तव में बेहतर है क्योंकि आप केवल 'कंट्रोल टेम्पलेट' को ओवरराइड करने वाले बनाम कनवर्टर का उपयोग कर रहे हैं; हालांकि, यह केवल तभी काम करता है जब आप मेरे मामले में 'स्क्रॉल व्यूअर' की 'पैडिंग', _not_' मार्जिन 'से जुड़ें। –

0

मैं में भाग पर Padding प्रॉपर्टी को सेट करते समय यह समस्या, और पैडिंग प्रॉपर्टी को बंद करके इसे चारों ओर मिला, लेकिन शून्य के बराबर नहीं:

<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> 
संबंधित मुद्दे