wpf 如何在 UserControl 中使用 ContentPresenter
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36446440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use a ContentPresenter inside a UserControl
提问by Th1sD0t
I'd like to create a UserControl (in this case a square-Button with defined Backgroundcolors) which can host it's own content.
我想创建一个 UserControl(在这种情况下是一个带有定义背景颜色的方形按钮),它可以托管它自己的内容。
UserControl:
用户控件:
<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>
Now, as you may expect it, if I use this Control inside my MainView everthing works just fine until I define some Content.
现在,如您所料,如果我在 MainView 中使用此控件,则一切正常,直到我定义了一些内容。
Using:
使用:
<control:ModernButton Size="200" BackgroundColor="Light">
TEST
</control:ModernButton>
In this case "TEST" will override the whole Content of the UserControl (the whole Button Template). I guess this happens because The Button inside the UserControl is defined as "Content" itself and it will get overridden when defining new Content.
在这种情况下,“TEST”将覆盖 UserControl 的整个内容(整个按钮模板)。我猜这是因为 UserControl 中的 Button 本身被定义为“内容”,并且在定义新内容时它会被覆盖。
So the final question is: Is it possible to achieve what I'm looking for? if yes: How? How could I "redirect" the Content I'm defining in my MainView into the self-defined ContentPresenter inside my Button Template instead of the UserControls's ContentPresenter?
所以最后一个问题是:是否有可能实现我正在寻找的东西?如果是:如何?如何将我在 MainView 中定义的内容“重定向”到我的按钮模板中的自定义 ContentPresenter 而不是 UserControls 的 ContentPresenter 中?
If possible I don't want to create a new dp-propery which hosts my Content, e.g.:
如果可能,我不想创建一个新的 dp-propery 来托管我的内容,例如:
<controls:MordernButton Size="200" BackgroundColor="Light">
<controls:ModernButton.Content>
I don't want this, if possible
</controls:ModernButton.Content>
</controls:ModernButton>
采纳答案by Gopichandar
Here we go.
开始了。
<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>
回答by Sriram Sakthivel
Use the ContentPropertyAttributeto instruct the xaml to set this property instead of the actual Content property.
使用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); }
}
}
Then in your xaml, Bind the Content Presenter to use InnerContent property instead.
然后在您的 xaml 中,绑定 Content Presenter 以使用 InnerContent 属性。
<ContentPresenter Content="{Binding InnerContent, ElementName=_modernButton}"/>
This way you can do the following without replacing the actual content.
这样您就可以在不替换实际内容的情况下执行以下操作。
<control:ModernButton Size="200" BackgroundColor="Light">
TEST
</control:ModernButton>
回答by Noam M
Let's assume that youre UserControl is:
让我们假设您的 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>
Note the TargetType property on the template: without it the project will happily compile, but the ContentPresenter will not work. And then:
请注意模板上的 TargetType 属性:没有它,项目将很容易编译,但 ContentPresenter 将无法工作。进而:
<Window ... >
<StackPanel Orientation="Vertical">
<local:Decorator>
<Label Background="Wheat">User supplied content here</Label>
</local:Decorator>
</StackPanel>
</Window>
I strongly recommend you to read thisbefore implementing anything
我强烈建议您在执行任何操作之前阅读此内容
回答by Logan
Simple; Just circumvent and replace the UserControl's Template.
简单的; 只需绕过并替换 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>
All a user control is (at least it terms of XAML and its template), is a Border with a ContentPresenter inside it. The ContentPresenter being the only important part, really.
所有用户控件都是(至少是 XAML 及其模板的术语),是一个带有 ContentPresenter 的边框。ContentPresenter 是唯一重要的部分,真的。
So all you do is gut out its Template and feed the Content property the UserControl has into something a little different; in this case, your button.
所以你要做的就是删除它的 Template 并将 UserControl 的 Content 属性输入一些不同的东西;在这种情况下,您的按钮。
This is the difference between making a usercontrol out ofother controls, and shoving some controls intoa user control. Making the usercontrol out of other controls gives you much more power.
这是从其他控件中制作用户控件与将某些控件推入用户控件之间的区别。使用户控件脱离其他控件可为您提供更多功能。

