2016-04-06 17 views
6

我想創建一個UserControl(在本例中是一個帶定義的Backgroundcolors的方形按鈕),它可以託管它自己的內容。如何在UserControl中使用ContentPresenter

用戶控件:

<UserControl x:Class="SGDB.UI.Controls.ModernButton" 
     xmlns:local="clr-namespace:SGDB.UI.Controls" 
     xmlns:converter="clr-namespace:SGDB.UI.Converter" 
     x:Name="_modernButton"> 
<Button> 
    <Button.Resources> 
     <converter:EnumToColorConverter x:Key="ColorConverter"/> 
    </Button.Resources> 
    <Button.Template> 
     <ControlTemplate> 
      <Border Width="{Binding Size, ElementName=_modernButton}" Height="{Binding Size, ElementName=_modernButton}" BorderBrush="Black" BorderThickness="0.8,0.8,3,3"> 
       <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}"> 
        <ContentPresenter/> 
       </Grid> 
      </Border> 
     </ControlTemplate> 
    </Button.Template> 
</Button> 

現在,你可能會想到吧,如果我用我的MainView這裏面控制,直到我定義了一些內容寄託都工作得很好。

使用:

<control:ModernButton Size="200" BackgroundColor="Light"> 
    TEST 
</control:ModernButton> 

在這種情況下「TEST」將覆蓋用戶控件(全按鍵模板)的全部內容。我猜這是因爲UserControl內部的按鈕被定義爲「內容」本身,並且在定義新內容時它將被覆蓋。

所以最後的問題是:是否有可能實現我在找的東西?如果是的話:如何?我如何將我在MainView中定義的內容「重定向到」我的按鈕模板中的自定義ContentPresenter而不是UserControls的ContentPresenter?

如果可能的話,我不希望創建一個新的DP-屬性格式它承載我的內容,例如:

<controls:MordernButton Size="200" BackgroundColor="Light"> 
    <controls:ModernButton.Content> 
     I don't want this, if possible 
    </controls:ModernButton.Content> 
</controls:ModernButton> 
+0

你是說你不想爲此創建新的dp? – Gopichandar

+0

正確 - 如果可能的話,當然。 – C4p741nZ

+0

@ Chill-X請參閱下面的答案。如果您遇到任何問題,請告訴我。 – Gopichandar

回答

5

在這裏,我們再走。

<UserControl x:Class="SGDB.UI.Controls.ModernButton" 
    xmlns:local="clr-namespace:SGDB.UI.Controls" 
    xmlns:converter="clr-namespace:SGDB.UI.Converter" 
    x:Name="_modernButton"> 

    <UserControl.Template> 
     <ControlTemplate TargetType="UserControl"> 
      <Button Content="{TemplateBinding Content}"> 
       <Button.Resources> 
        <converter:EnumToColorConverter x:Key="ColorConverter"/> 
        </Button.Resources> 
      <Button.Template > 
       <ControlTemplate TargetType="Button"> 
        <Border Width="{Binding Size, 
            ElementName=_modernButton}" 
        Height="{Binding Size, 
            ElementName=_modernButton}" 
        BorderBrush="Black" 
        BorderThickness="0.8,0.8,3,3"> 
         <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}"> 
          <ContentPresenter /> 
         </Grid> 
        </Border> 
       </ControlTemplate> 
      </Button.Template> 
      </Button> 
     </ControlTemplate> 
    </UserControl.Template> 
</UserControl> 
+0

起初它看起來非常好 - 但是當傳遞一些內容(「TEST」或)時,什麼都沒有顯示 - 控件保持空白(除了它自己的顏色) – C4p741nZ

+0

就是這樣 - 你能解釋爲什麼Button的TargetType對ContentPresenter有如此大的影響嗎?如果你在上面,也許你可以解釋爲什麼按鈕的模板綁定在將某些內容傳遞給控件時阻止WPF清除整個內容?在此先感謝:) – C4p741nZ

+1

這將是一個很大的話題來覆蓋。可能[this](http://stackoverflow.com/a/3632926/2819451)回答你的第一個問題。 – Gopichandar

2

讓我們假設您選擇用戶控件是:

<UserControl x:Class="QuickAndDirtyAttempt.Decorator" .... 
     <UserControl.Template> 
     <ControlTemplate TargetType="{x:Type local:Decorator}"> 
      <StackPanel Orientation="Vertical"> 
      <Label>Foo</Label> 
      <ContentPresenter/> 
      <Label>Bar</Label> 
      </StackPanel> 
     </ControlTemplate> 
     </UserControl.Template> 
</UserControl> 

注意的TargetType屬性在模板上:沒有它,該項目將愉快地編譯,但ContentPresenter不起作用。 然後:

<Window ... > 
    <StackPanel Orientation="Vertical"> 
     <local:Decorator> 
      <Label Background="Wheat">User supplied content here</Label> 
     </local:Decorator> 
    </StackPanel> 
</Window> 

我強烈建議你read this實現什麼

+0

我讀過但讀過的部分說:「沒有TargetType的項目將愉快地編譯,但ContentPresenter將無法正常工作」。你應該得到我的贊成,因爲CodeProject解釋了爲什麼不應該使用我的解決方案:) – C4p741nZ

2

簡單;只是繞過並替換UserControl的模板。

<UserControl.Template> 
     <ControlTemplate TargetType="{x:Type UserControl}"> 
      <Button Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"> 
       <Button.Resources> 
        <converter:EnumToColorConverter x:Key="ColorConverter"/> 
       </Button.Resources> 
       <Button.Template> 
        <ControlTemplate TargetType="{x:Type Button}"> 
         <Border Width="{Binding Size, 
             ElementName=_modernButton}" 
         Height="{Binding Size, 
             ElementName=_modernButton}" 
         BorderBrush="Black" 
         BorderThickness="0.8,0.8,3,3"> 
          <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}"> 
           <ContentPresenter /> 
          </Grid> 
         </Border> 
        </ControlTemplate> 
       </Button.Template> 
      </Button> 
     </ControlTemplate> 
    </UserControl.Template> 

所有的用戶控件(至少XAML和模板的它而言),是內部具有ContentPresenter邊框。 ContentPresenter是唯一重要的部分,真的。

因此,你所要做的就是將模板提取出來,並將UserControl的Content屬性提供給一些有點不同的東西;在這種情況下,你的按鈕。

這是製作一個usercontrol 出的其他控制,推搡和一些控制用戶控件之間的差異。 使用戶控制離開其他控件可以提供更多的功能。

+1

如果第二個ControlTemplate的類型是「按鈕」,也可以這樣做。 – C4p741nZ

+0

哦,是的,我怎麼錯過了? - 編輯它。 – Logan

10

使用ContentPropertyAttribute來指示xaml設置此屬性而不是實際的Content屬性。

[ContentProperty("InnerContent")] 
public partial class ModernButton : UserControl 
{ 
    public ModernButton() 
    { 
     InitializeComponent(); 
    } 

    public static readonly DependencyProperty InnerContentProperty = 
     DependencyProperty.Register("InnerContent", typeof(object), typeof(ModernButton)); 

    public object InnerContent 
    { 
     get { return (object)GetValue(InnerContentProperty); } 
     set { SetValue(InnerContentProperty, value); } 
    } 
} 

然後在您的xaml中,將Content Presenter綁定爲使用InnerContent屬性。

<ContentPresenter Content="{Binding InnerContent, ElementName=_modernButton}"/> 

這樣,您可以在不更換實際內容的情況下執行下列操作。

<control:ModernButton Size="200" BackgroundColor="Light"> 
    TEST 
</control:ModernButton> 
+2

也能工作。但我想知道XAML是如何工作的 - 我真的不喜歡用特性來裝飾代碼。 – C4p741nZ

+0

棒極了!由於它不是模板覆蓋,因此您可以輕鬆定義名稱和代碼鏈接 –

相關問題