Wpf 把我的蛋糕也吃了:把一个容器和它绑在一起';内容

Wpf 把我的蛋糕也吃了:把一个容器和它绑在一起';内容,wpf,xaml,custom-controls,Wpf,Xaml,Custom Controls,我有一个自定义控件Cake,它包含两个名为Slice和Filling的DependencyProperties如何创建一种既可以访问切片,又可以设计切片的样式? <Style TargetType={x:Type local:Cake}> //I don't like setting DataContext Here <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSo

我有一个自定义控件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>

//我不喜欢在这里设置DataContext
我尝试过的选项:

  • 我不能使用UserControl,因为我想允许命名内容,这显然不适用于用户控件。看

  • 我不喜欢上面的例子,因为我必须将蛋糕容器的DataContext设置为self,这意味着用户不能将DataContext用于他们的应用程序 绑定

  • 我无法使用RelativeSource绑定Filling属性,因为有几个 蛋糕,样式不知道哪一个是正确的父母。看见

  • 我可以直接用切片元素替换内容演示器, 但是因为它在一个模板中,我在任何地方都无法访问切片 在模板之外。虽然我可能会在visualTree中输入到切片,但这感觉就像一场维护噩梦

我基本上希望每个蛋糕都有一片,并且能够使用

<Cake.Slice>
    <DockPanel>
       <Rectangle Background= “Blue”/>
       <Rectangle Background= “Blue”/>
       <Rectangle Background=“{Binding Filling}”/>
    </DockPanel>
</Cake.Slice>

同时也给它一个默认的外观

编辑:
显然,如果我引用的是与Cake项目相反的Cake.dll,那么我的风格确实有效。为什么会这样呢?

这并不是你所需要的,但我希望它能为你指明如何实现这一目标

首先,您不需要将
DataContext
设置到控件本身,您可以使用
{TemplateBinding Slice}
从Cake的ControlTemplate绑定到Cake控件上的属性(填充和切片),这只是
{Binding Slice,RelativeSource={RelativeSource TemplatedParent}
(因此您可以使用其中一个)

这将是控件的简化版本,因为我不知道控件模板中的ItemPresenter应该显示哪些项目,或者切片和填充属性的类型。在本例中,填充是
SolidColorBrush
,切片是
样式
。该样式应用于具有在Cake的
ControlTemplate
中,您可以为切片预定义样式,并应用您选择的填充(如果切片属性有不同的用途,您可以引入另一个名为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):


不同的切片样式(这些是为ContentControl设置ControlTemplate,这样您就不会碰到问题中的问题3):


以及正在使用的控件:

<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>


祝你胃口好!

你有一张你想在蛋糕中实现什么的图片吗?@AyyappanSubramanian Yep,刚刚加了一张。虽然这仍然不能让我直接访问切片,但它做了一件很棒的工作,让我可以设计它-感谢你找到了使用相对资源的方法!
<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>