2017-11-17 233 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