I want to create an attached property that can be used with this syntax:
<Button>
<Image .../>
<ui:ToolbarItem.DisplayFilter>
<TabItem .../>
<TabItem .../>
<TabItem .../>
</ui:ToolbarItem.DisplayFilter>
</Button>
This is my attempt at doing so:
public class ToolbarItem
{
/// <summary>
/// Identifies the DisplayFilter attached property.
/// </summary>
public static readonly DependencyProperty DisplayFilterProperty =
DependencyProperty.RegisterAttached(
"DisplayFilter",
typeof( IList ),
typeof( ToolbarItem )
);
public static IList GetDisplayFilter( Control item ) {
return (IList)item.GetValue( DisplayFilterProperty );
}
public static void SetDisplayFilter( Control item, IList value ) {
item.SetValue( DisplayFilterProperty, value );
}
}
This, however, is causing an exception at parse-time — System.ArgumentException: TabItem is not a valid value for property ‘DisplayFilter’. So how do I configure my attached property so that I can use the desired XAML syntax?
Remember that XAML is basically just a shorthand form of object creation. So to create a collection/list as the value for the attached
DisplayFilterproperty you would have to enclose thoseTabItemsinside another collection tag. If you don’t want to do that, which is understandable, you have to initialize the collection the first time the property is accessed.There is just one problem with this: The getter method is skipped by the XAML reader as an optimization. You can prevent this behavior by choosing a different name for the name argument to the
RegisterAttachedcall:Then the property getter will be called and you can check for
null. You can read more about that in this blog post.Edit: Seems like the linked blog post isn’t that clear. You change only the name of the string passed to
RegisterAttached, not the name of the static get/set methods:You have to initialize the collection in the
GetDisplayFiltermethod:It seems that you only add
TabItemelements to that collection. Then you can make the collection type-safe, but usingIList<T>does not work since the XAML parser cannot invoke the generic methodAdd(T).Collection<T>andList<T>also implement the non-genericIListinterface and can be used in this case. I would suggest to create a new collection type in case you want to do some changes to the collection in the future:If you don’t care about setting the collection explicitly like this:
you can remove the
SetDisplayFiltermethod.To summarize: