WPF: dependency property with type of Template - where to get default template (to set as default value)?
I am subclassing an ItemsControl (let's call it EnhancedItemsControl), and I would like to expose ScrollViewerTemplate dependency property, which would allow the user to optionally specify his own template for used ScrollViewer. I am doing it like this:
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
In my default style for my EnhancedItemsControl, I then include the ScrollViewer like this:
<ScrollViewer
Template="{TemplateBinding ScrollViewerTemplate}"
...
>
<ItemsPresenter
...
/>
</ScrollViewer>
This works when the user specifies the ScrollViewerTemplate, but when he leaves it at default value, the ScrollViewer is not displayed (presumably because it's Template is empty). How can I tell WPF Use the Template only when it is non-null, otherwise use default one? (it occured to me that I could use trigg开发者_开发百科ers to set the Template only when it is not null, but I don't like the idea of having a trigger for every custom property in each of my controls...)
There is similar problem with styles - if I wanted to let user specify the ScrollViewer style, but the user didn't specify it, the value of ScrollViewerStyle would be null (equal to <ScrollViewer Style="{x:Null}" />
), which would stop the default style from being applied!
How to solve this? Thank you!
You're doing everything right except one little bit, the default value you are specifying in your UIPropertyMetadata
is actually null, because it's null in that new ScrollViewer
as well by default.
Instead of defining a ScrollViewerTemplate
property, define a ScrollViewerStyle
property:
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));
And in your default style for the control, specify a default value for the style as such:
<Setter Property="ScrollViewerStyle" Value="{StaticResource {x:Type ScrollViewer}}"/>
This will actually default to the ScrollViewer style as defined by the current theme.
Instead of using TemplateBinding you can use Binding with RelativeSource of TemplatedParent. This way you will be able to use converter in your Binding. Now declare a Converter(IValueConverter) for your Binding and return the default Template while the ScrollViewerTemplate property is null.
More Information
精彩评论