2017-11-17 236 views
1

我有一個自定義控件Cake,它包含兩個名爲Slice和Filling的DependencyProperties。 如何創建一種讓我可以使用切片的風格,同時也讓我設計切片?我的蛋糕也吃了它:綁定容器和它的內容

<Style TargetType={x:Type local:Cake}> 
    //I don't like setting DataContext Here 
    <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource Self}}/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType={x:Type local:Cake}> 
       <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">       

        //This is how I display a slice 
        <ContentPresenter Content={Binding Slice}/> 

        //This is how cake decorations are displayed 
        <ItemsPresenter/> 

       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="Slice"> 
     <Setter.Value> 

      //Design Slice Here - it's easy to override when I want 
      <Slice Filling={Binding Filling}> // it's just in a setter. 

     </Setter.Value> 
    </Setter> 
    <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource Self}}/> 
</Style> 

選項我已經試過:

  • 我不能使用一個用戶控件,因爲我想允許指定的內容,這顯然不符合用戶控件工作。見Here.

  • 我不喜歡上面的例子,因爲我必須設置的DataContext蛋糕容器的自我,這就意味着用戶不能使用的DataContext爲他們 綁定。

  • 我無法使用RelativeSource綁定Filling屬性,因爲有幾個 的蛋糕,Style將不知道哪一個是正確的父級。見 Here.

  • 我可以用一個片元素, 直接更換內容呈現,但因爲它是一個模板,我鬆訪問切片任何地方 模板之外。雖然我可能會將視覺樹切成片,但這感覺是一場維護噩夢。

Access Slice from Cake Directly, but be able to edit it in xaml

我基本上希望每個蛋糕有一個切片,並用

<Cake.Slice> 
    <DockPanel> 
     <Rectangle Background= 「Blue」/> 
     <Rectangle Background= 「Blue」/> 
     <Rectangle Background=「{Binding Filling}」/> 
    </DockPanel> 
</Cake.Slice> 

同時也給它一個默認外觀要能設置。

編輯: 顯然,我的風格不工作,前提是我引用Cake.dll,而不是蛋糕項目。爲什麼會這樣?

+0

你有沒有想要在蛋糕中實現的圖片? –

+0

@AyyappanSubramanian是的,只是加了一個。 – bwall

回答

1

這不會正是你所需要的,但我希望它會給你指示如何實現這一點。

首先,你並不需要設置DataContext到控制本身,你可以從蛋糕的控件模板使用{TemplateBinding Slice}綁定屬性蛋糕上的控制(灌裝切片),這僅僅是{Binding Slice, RelativeSource={RelativeSource TemplatedParent}}快捷方式(這樣你就可以使用一個或另一個)。

這將是您的控件的簡化版本,因爲我不知道ControlTemplate中的ItemPresenter應顯示哪些項目,或者您的Slice和Filling屬性的類型是什麼。在這個例子中,Filling是SolidColorBrush,而Slice是Style。該樣式適用於Cake的ControlTemplate中的ContentControl,因此您可以爲切片預定義樣式,並應用填充選項(如果Slice屬性具有不同的用途,則可以引入另一個屬性,例如SliceStyle)。

蛋糕控制:

public class Cake : Control 
{ 
    static Cake() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(
      typeof(Cake), 
      new FrameworkPropertyMetadata(typeof(Cake))); 
    } 

    public SolidColorBrush Filling 
    { 
     get { return (SolidColorBrush)GetValue(FillingProperty); } 
     set { SetValue(FillingProperty, value); } 
    } 

    public static readonly DependencyProperty FillingProperty = 
     DependencyProperty.Register(
      "Filling", 
      typeof(SolidColorBrush), 
      typeof(Cake), 
      new PropertyMetadata(Brushes.Transparent)); 

    public Style Slice 
    { 
     get { return (Style)GetValue(SliceProperty); } 
     set { SetValue(SliceProperty, value); } 
    } 

    public static readonly DependencyProperty SliceProperty = 
     DependencyProperty.Register(
      "Slice", 
      typeof(Style), 
      typeof(Cake), 
      new PropertyMetadata(null)); 
} 

默認風格(Generic.xaml):

<Style TargetType="{x:Type local:Cake}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:Cake}"> 
       <ContentControl Width="{TemplateBinding Width}" 
           Height="{TemplateBinding Height}" 
           Style="{TemplateBinding Slice}"/> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

不同的切片風格(這些設置控件模板爲ContentControl中,這樣你就不會打在發行數3你的問題):

<Window.Resources> 
    <Style x:Key="TwoLayeredSlice" TargetType="{x:Type ContentControl}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="*"/> 
          <RowDefinition Height="*"/> 
         </Grid.RowDefinitions> 
         <Rectangle Fill="{Binding Filling, 
          RelativeSource={RelativeSource AncestorType={x:Type local:Cake}}}"/> 
         <Rectangle Fill="Brown" 
            Grid.Row="1"/> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style x:Key="FourLayeredSlice" TargetType="{x:Type ContentControl}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="*"/> 
          <RowDefinition Height="*"/> 
          <RowDefinition Height="*"/> 
          <RowDefinition Height="*"/> 
         </Grid.RowDefinitions> 
         <Rectangle Fill="{Binding Filling, 
          RelativeSource={RelativeSource AncestorType={x:Type local:Cake}}}"/> 
         <Rectangle Fill="Brown" 
            Grid.Row="1"/> 
         <Rectangle Fill="{Binding Filling, 
          RelativeSource={RelativeSource AncestorType={x:Type local:Cake}}}" 
            Grid.Row="2"/> 
         <Rectangle Fill="Brown" 
            Grid.Row="3"/> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

而在使用中的控制:

<Grid Background="Gray"> 
    <local:Cake Width="200" 
       Height="100" 
       HorizontalAlignment="Left" 
       Filling="Gold" 
       Slice="{StaticResource TwoLayeredSlice}"/> 
    <local:Cake Width="200" 
       Height="100" 
       HorizontalAlignment="Center" 
       Filling="Pink" 
       Slice="{StaticResource FourLayeredSlice}"/> 
    <local:Cake Width="200" 
       Height="100" 
       HorizontalAlignment="Right" 
       Filling="Blue" 
       Slice="{StaticResource FourLayeredSlice}"/> 
</Grid> 

Cakes

個飽!

+0

雖然這仍然不能直接訪問該切片,但它還是讓我設計它的一個**夢幻般的工作 - 感謝您找到一種使用RelativeSource的方法! – bwall