
Requirements for Properties of a Custom Class as XAML Attributes
Properties must reference a by-value type (such as a primitive), or use a class for type that has either a default constructor or a dedicated type converter at the class level.
Alternatively, the property may reference an abstract class type, or an interface. For abstract classes or interfaces, the expectation at run time is that the property value must be filled with practical class instances that implement the interface, or class instances that derive from the abstract class.
Properties can be declared on an abstract class, but can only be set on practical classes that derive from the abstract class, because creating the object element for the class at all requires a public default constructor on the class.
Type-converter Enabled Attribute Syntax
If you provide a dedicated, attributed type converter at the class level, the applied type conversion enables attribute syntax for any property that needs to instantiate that type. A type converter does not enable object element usage of the type; only the presence of a default constructor for that type enables object element usage. Therefore, properties that are type-converter enabled are generally speaking not usable in property syntax, unless the type itself also supports object element syntax. The exception to this is that you can specify a property element syntax, but have the property element contain a string. That usage is really essentially equivalent to an attribute syntax usage, and such a usage is not common unless there is a need for more robust whitespace handling of the attribute value. For example, the following is a property element usage that takes a string, and the attribute usage equivalent:
<Button>Hallo!
<Button.Language>
de-DE
</Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>
Examples of properties where attribute syntax is allowed but property element syntax that contains an object element is disallowed through XAML are various properties that take the Cursor type. The Cursor class has a dedicated type converter CursorConverter, but does not expose a default constructor, so the Cursor property can only be set through attribute syntax even though the actual Cursor type is a reference type.
Per-Property Type Converters
Alternatively, the property itself may declare a type converter at the property level. This enables a "mini language" that instantiates objects of the type of the property inline, by processing incoming string values of the attribute as input for a ConvertFrom operation based on the appropriate type. Typically this is done to provide a convenience accessor, and not as the sole means to enable setting a property in XAML. However, it is also possible to use type converters for attributes where you want to use existing CLR types that do not supply either a default constructor or an attributed type converter. Examples from the WPF APIs are certain properties that take the CultureInfo type. In this case, WPF used the existing Microsoft .NET Framework CultureInfo type to better address compatibility and migration scenarios that were used in earlier versions of frameworks, but the CultureInfo type did not support the necessary constructors or type-level type conversion to be usable as a XAML property value directly.
Whenever you expose a property that has a XAML usage, particularly if you are a control author, you should strongly consider backing that property with a dependency property. This is particularly true if you use the existing Windows Presentation Foundation (WPF) implementation of the XAML processor, because you can improve performance by using DependencyProperty backing. A dependency property will expose property system features for your property that users will come to expect for a XAML accessible property. This includes features such as animation, data binding, and style support. For more information, see Custom Dependency Properties and XAML Loading and Dependency Properties.
Writing and Attributing a Type Converter
You frequently will need to write a custom TypeConverter derived class to provide type conversion for your property type. For instructions on how to derive from and create a type converter that can support XAML usages, and how to apply the TypeConverterAttribute, see TypeConverters and XAML.