我正在创建一个应该有多个内容插槽的自定义WPF控件。 我希望用户能够使用字符串或FrameworkElement作为属性值,例如:
<!-- MyHeading is a string -->
<MyControl MyHeading="Hello World" />
<MyControl>
<!-- MyHeading is a FrameworkElement -->
<MyControl.MyHeading>
<Expander Header="Hello">
World
</Expander>
</MyControl.MyHeading>
</MyControl>
我知道WPF ContentControl这样做(接受字符串和其他元素),我知道它与TypeConverter
属性(partially explained here)有关,但我试着看一下ContentControl ,Reflector中的Label,TextBlock和其他控件,并没有找到任何TypeConverter atrribute,谷歌搜索没有帮助。
我首先尝试像这样实现它,但它显然不知道如何将字符串转换为FrameworkElement,并在控件初始化期间抛出异常:
public FrameworkElement Heading
{
get { return (FrameworkElement)GetValue(HeadingProperty); }
set { SetValue(HeadingProperty, value); }
}
// Using a DependencyProperty as the backing store for Heading. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeadingProperty =
DependencyProperty.Register("Heading", typeof(object), typeof(DialogControl), new UIPropertyMetadata(new FrameworkElement()));
然后我试着像这样破解它:
public object Heading
{
get { return (object)GetValue(HeadingProperty); }
set
{
if (value is string)
{
var tb = new TextBlock();
tb.Text = (string) value;
tb.FontSize = 20;
SetValue(HeadingProperty, tb);
}
else if (value is FrameworkElement)
{
SetValue(HeadingProperty, value);
} else
throw new ArgumentOutOfRangeException("Heading can take only string or FrameworkElement.");
}
}
// Using a DependencyProperty as the backing store for Heading. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeadingProperty =
DependencyProperty.Register("Heading", typeof(object), typeof(DialogControl), new UIPropertyMetadata(null));
但它非常难看,仍然没有实例化:(。
任何人都知道怎么做?谢谢你的时间!
答案 0 :(得分:3)
DependencyProperty应为Object类型。当您将属性绑定为ContentPresenter的内容时,会发生魔力。如果要正确处理Templating和StringFormatting,还应该查看ContentSource属性。
答案 1 :(得分:1)
正如布莱恩所说,只是使用对象作为你的类型。当WPF遇到非frameworkelement时,它将(假设没有要应用的DataTemplate)调用对象的ToString()方法并使用该文本作为内容。因此,您不仅可以使用字符串,还可以使用DateTime,Enum,等等。
此外,如果您的控件同时具有标题和主要内容,则应考虑从HeaderedContentControl派生。然后你不需要实现这两个内容属性中的任何一个,你将免费得到所有的花里胡哨,如数据模板。
答案 2 :(得分:0)
正如其他人所说,将类型设置为对象。要进行类型检查,请在依赖项属性上使用验证回调。然后检查有效类型。
public object Header
{
get { return (object)GetValue(HeadingProperty); }
set { SetValue(HeadingProperty, value); }
}
// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeadingProperty = DependencyProperty.Register(
"Heading",
typeof(object),
typeof(DialogControl),
new UIPropertyMetadata(null),
new ValidateValueCallback(Heading_Validation)
);
private static bool Heading_Validation(object source)
{
return source is string||
source is FrameworkElement ||
source == null;
}
这将在赋值之前检查传递的对象是否为String,FrameworkElement或null类型。
享受!