如何在UserControl中使用ContentPresenter

C4p*_*1nZ 11 c# wpf xaml user-controls contentpresenter

我想创建一个UserControl(在这种情况下是一个带有已定义Backgroundcolors的方形按钮),它可以托管它自己的内容.

用户控件:

<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>
Run Code Online (Sandbox Code Playgroud)

现在,正如您所期望的那样,如果我在MainView中使用此控件,那么在我定义一些内容之前就可以正常工作.

使用:

<control:ModernButton Size="200" BackgroundColor="Light">
    TEST
</control:ModernButton>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,"TEST"将覆盖UserControl的整个内容(整个按钮模板).我想这是因为UserControl中的Button被定义为"Content"本身,并且在定义新内容时会被覆盖.

所以最后一个问题是:有可能实现我正在寻找的东西吗?如果是的话:怎么样?我怎样才能将我在MainView中定义的内容"重定向"到我的Button模板中的自定义ContentPresenter而不是UserControls的ContentPresenter?

如果可能的话,我不想创建一个托管我的内容的新dp-propery,例如:

<controls:MordernButton Size="200" BackgroundColor="Light">
    <controls:ModernButton.Content>
        I don't want this, if possible
    </controls:ModernButton.Content>
</controls:ModernButton>
Run Code Online (Sandbox Code Playgroud)

Sri*_*vel 16

使用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); }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的xaml中,绑定Content Presenter以使用InnerContent属性.

<ContentPresenter Content="{Binding InnerContent, ElementName=_modernButton}"/>
Run Code Online (Sandbox Code Playgroud)

这样,您可以在不替换实际内容的情况下执行以下操作.

<control:ModernButton Size="200" BackgroundColor="Light">
    TEST
</control:ModernButton>
Run Code Online (Sandbox Code Playgroud)

  • 工作也是.但我想知道XAML中的工作原理 - 我真的不喜欢用属性来装饰代码. (3认同)

Gop*_*dar 9

开始了.

<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>
Run Code Online (Sandbox Code Playgroud)

  • 回答你第二个问题。帮助我们停止清除整个内容的并不是 Button 的模板绑定。它的用户控件的模板绑定完成了它的工作。 (2认同)

Noa*_*m M 5

让我们假设您的 UserControl 是:

<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>
Run Code Online (Sandbox Code Playgroud)

请注意模板上的 TargetType 属性:如果没有它,项目将很容易编译,但 ContentPresenter 将无法工作。进而:

<Window ... >
    <StackPanel Orientation="Vertical">
        <local:Decorator>
            <Label Background="Wheat">User supplied content here</Label>
        </local:Decorator>
    </StackPanel>
</Window> 
Run Code Online (Sandbox Code Playgroud)

我强烈建议您在执行任何操作之前阅读此内容