2016-07-06 64 views
2

所以,我有一個名爲WatermarkTextbox的自定義WPF控件,它擴展了TextBox。我添加到代碼中的唯一東西是一個字符串依賴項屬性來保存水印文本。其餘的魔法在Xaml(下面)。使用自定義WPF控件時無法設置一些屬性

<Style TargetType="wpfControls:WatermarkTextbox" > 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type wpfControls:WatermarkTextbox}"> 
       <Grid> 
        <TextBox x:Name="baseTextBox" /> 
        <TextBlock Margin="5,0,0,0" x:Name="watermarkText" IsHitTestVisible="False" FontWeight="Light" FontStyle="Italic" Foreground="DarkGray" Visibility="Hidden" Background="Transparent" 
           Text="{Binding RelativeSource={RelativeSource AncestorType=wpfControls:WatermarkTextbox}, Path=Watermark}" /> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <Trigger SourceName="baseTextBox" Property="Text" Value=""> 
         <Setter TargetName="watermarkText" Property="Visibility" Value="Visible"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

,並在我的應用程序使用時:

<wpfControls:WatermarkTextbox Watermark="Text that disappears."/> 

此作品居多。我可以設置水印文本,當我開始輸入一些文本時,它會消失。當我更改字體大小時,它會更改水印和我輸入的文本;當我改變字體重量時,它只會改變輸入的文本(這是我想要的)。我可以改變文本框的大小。這都是肉汁。

問題是,當我開始嘗試改變像文本框的背景或邊框屬性,像這樣。

<wpfControls:WatermarkTextbox Watermark="Text that disappears." Background="Yellow"/> 

什麼也沒有發生。與BorderBrush和BorderThickness具有相同的行爲。現在,我所知道的部分正好足以讓我知道有一些我不知道的重要概念。如果我將我的WatermarkTextbox的模板更改爲以下內容,它會讓我像我想要的那樣在應用程序中設置背景。

<Style TargetType="wpfControls:WatermarkTextbox" > 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type wpfControls:WatermarkTextbox}"> 
       <Grid> 
        <TextBox x:Name="baseTextBox" 
          Background="{TemplateBinding Background}"/> 
        <TextBlock Margin="5,0,0,0" x:Name="watermarkText" IsHitTestVisible="False" FontWeight="Light" FontStyle="Italic" Foreground="DarkGray" 
           Text="{Binding RelativeSource={RelativeSource AncestorType=wpfControls:WatermarkTextbox}, Path=Watermark}" Visibility="Hidden" Background="Transparent"/> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <Trigger SourceName="baseTextBox" Property="Text" Value=""> 
         <Setter TargetName="watermarkText" Property="Visibility" Value="Visible"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

我認爲如果我爲BorderBrush和BorderThickness做了同樣的工作,它們也可以工作。

所以,我的問題是,爲什麼?這些屬性使它們的行爲與FontSize和FontWeight或Height和Width的行爲有什麼不同?爲什麼我必須將背景明確設置爲{TemplateBinding Background}而不是FontSize?另外,爲了使它們正常工作,還需要將其他屬性設置爲TemplateBinding?

回答

3

某些屬性自動從其父項繼承。 explanation

這就是您不必設置FontSize的原因。

至於「還有什麼」,這一切都取決於你希望能夠直接在用戶控件上設置什麼。

雖然這不是防彈的,但我的一般經驗法則是「如果它是一個屬性在屬性窗口中的Brush Tab或純粹是爲了視覺美感,它可能是不能繼承」

看看它的另一種方式 - 如果設置會給一般怪異的結果,它也可能不會被繼承。例如:如果您將Margin屬性設置爲Grid,請試想每個子元素是否都繼承了相同的邊距。

所以我通常爲所有非佈局,可視屬性(Background, Foreground, BorderBrush, etc.)添加模板綁定。或者我只是爲我想直接設置到我的用戶控件的任何屬性添加templatebindings。如果您從不打算設置屬性(顯式或按樣式),則無需添加模板綁定。

+1

很好說:「如果設置會給一般的怪異結果,它也可能不會被繼承。例如:如果你在網格上設置Margin屬性,想象一下每個子元素是否都繼承了相同的邊距。 –

3

別的,你需要明確做TemplateBinding事情 - 或者它們是否會在運行時改變,你需要做的RelativeSource綁定:

{Binding PropertyName, RelativeSource={RelativeSource TemplatedParent}} 

沒有任何「第一原則」對此的解釋;這只是任意的實現細節。

相關問題