WPF:具有模板类型的依赖项属性 - 在哪里获取默认模板(设置为默认值)?

时间:2010-01-02 01:21:19

标签: wpf templates dependency-properties default-value

我正在继承ItemsControl(我们称之为EnhancedItemsControl),我想公开ScrollViewerTemplate依赖项属性,这将允许用户为使用过的ScrollViewer选择性地指定自己的模板。我是这样做的:

public ControlTemplate ScrollViewerTemplate
{
   get { return (ControlTemplate)GetValue(ScrollViewerTemplateProperty); }
   set { SetValue(ScrollViewerTemplateProperty, value); }
}

public static readonly DependencyProperty ScrollViewerTemplateProperty =
   DependencyProperty.Register(
   "ScrollViewerTemplate", 
   typeof(ControlTemplate), 
   typeof(EnhancedItemsControl),
   new UIPropertyMetadata(new ScrollViewer().GetValue(ScrollViewer.TemplateProperty))); //This doesn't work for me

在我的EnhancedItemsControl的默认样式中,然后我像这样包含ScrollViewer:

<ScrollViewer
   Template="{TemplateBinding ScrollViewerTemplate}"
   ...
>
    <ItemsPresenter
    ...
    />
</ScrollViewer>

当用户指定ScrollViewerTemplate时,此方法有效,但当他将其保留为默认值时,不会显示ScrollViewer(可能是因为它的模板为空)。如何告诉WPF 仅在非空时使用模板,否则使用默认模板? (它发生在我身上,我可以使用触发器仅在它不为空时设置模板,但我不喜欢在每个控件中为每个自定义属性设置触发器的想法......)

样式存在类似问题 - 如果我想让用户指定ScrollViewer样式,但用户没有指定它,则ScrollViewerStyle的值将为null(等于<ScrollViewer Style="{x:Null}" />),这将停止正在应用的默认样式!

如何解决这个问题?谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用Binding与TemplatedParent的RelativeSource代替使用TemplateBinding。这样您就可以在Binding中使用转换器。现在为Binding声明一个Converter(IValueConverter),并在ScrollViewerTemplate属性为null时返回默认模板。

More Information

答案 1 :(得分:1)

除了一点点之外你正在做的一切正确,你在UIPropertyMetadata中指定的默认值实际上是空的,因为默认情况下它在新的ScrollViewer中也是空的。

不要定义ScrollViewerTemplate属性,而是定义ScrollViewerStyle属性:

public Style ScrollViewerStyle
{
    get { return (Style)GetValue(ScrollViewerTemplateProperty); }
    set { SetValue(ScrollViewerTemplateProperty, value); }
}

public static readonly DependencyProperty ScrollViewerTemplateProperty =
    DependencyProperty.Register(
        "ScrollViewerStyle", 
        typeof(Style), 
        typeof(EnhancedItemsControl), 
        new UIPropertyMetadata(null));

在控件的默认样式中,为样式指定默认值:

<Setter Property="ScrollViewerStyle" Value="{StaticResource {x:Type ScrollViewer}}"/>

这实际上默认为当前主题定义的ScrollViewer样式。