CustomPropertyProviders
This tutorial describes how to use a custom property provider to define the properties that should be persisted by the PersistenceFramework.
The PersistenceFramework exposes an extension method that allows you to register a class to act as a property provider and define which properties of a persisted control should be saved and how. The method has the following syntax:
Example 1: Register Custom Provider
ServiceProvider.RegisterPersistenceProvider<ICustomPropertyProvider>(System.Type type, Telerik.Windows.Persistence.Services.IPersistenceProvider provider);
You need to pass as arguments the type of the component that will use the custom property provider and an instance of the custom property provider class.
A custom property provider should be used if:
- You need to persist more complex controls with complex properties such as the RadGridView.
- You need to have more control over the persistence process and specifically over the list of persisted properties and how they are provided to the PersistenceFramework for serialization.
The PersistenceFramework provides several providers which can be used to persist specific properties.
- ICustomPropertyProvider
- IAttachedPropertyProvider
- IPropertyProvider
- IPropertyValidatorProvider
- ITypeConverterProvider
ICustomPropertyProvider
The PersistenceFramework provides an ICustomPropertyProvider interface which you should implement in order to create a custom property provider. It exposes the following methods:
GetCustomProperties() - this method should return an array of CustomPropertyInfo objects to represent the list of properties that have to be persisted by the PersistenceFramework.
InitializeObject(object - this method is intended to place the context object (the control being persisted) in an appropriate state, before the PersistenceFramework starts loading the persisted settings.
InitializeValue(CustomPropertyInfo - this method is invoked to provide a valid value for a property when the deserialization fails to recreate the property's saved value (for example if it can't create a new instance of the class or the persisted value is null).
ProvideValue(CustomPropertyInfo - this method is invoked for each property from the array returned by the GetCustomProperties() method. It should return a proper value, which the PersistenceFramework can persist.
RestoreValue(CustomPropertyInfo - this method is invoked for each persisted property to restore its persisted value and load it.
Creating a custom property provider
You can implement the above methods in a custom property provider class as follows:
Example 2: Implement ICustomPropertyProvider interface
public class SampleCustomPropertyProvider : ICustomPropertyProvider
{
public CustomPropertyInfo[] GetCustomProperties()
{
// Create an array of CustomPropertyInfo objects to describe which properties should be persisted
return new CustomPropertyInfo[]
{
//Add CustomPropertyInfo objects
};
}
public void InitializeObject(object context)
{
//Set the persisted component in a state such that it is ready to take the persisted settings
}
public object InitializeValue(CustomPropertyInfo customPropertyInfo, object context)
{
//Return a default value for the properties which the PersistenceFramework failed to restore
}
public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
{
//Implement a logic that returns an object describing a property.
//Note that this event is fired once for each property from the array returned by the GetCustomProperties() method.
//Therefore you need to implement a logic that returns a separate object for each property.
}
public void RestoreValue(CustomPropertyInfo customPropertyInfo, object context, object value)
{
//Use the value argument to get the persisted settings.
//Apply these settings on the context object as it represents the persisted component
}
}
Public Class SampleCustomPropertyProvider
Implements ICustomPropertyProvider
Public Function GetCustomProperties() As CustomPropertyInfo()
' Create an array of CustomPropertyInfo objects to describe which properties should be persisted '
Return New CustomPropertyInfo() {}
End Function
Public Sub InitializeObject(context As Object)
'Set the persisted component in a state such that it is ready to take the persisted settings '
End Sub
Public Function InitializeValue(customPropertyInfo As CustomPropertyInfo, context As Object) As Object
'Return a default value for the properties which the PersistenceFramework failed to restore '
End Function
Public Function ProvideValue(customPropertyInfo As CustomPropertyInfo, context As Object) As Object
'Implement logic that returns an object describing a persisted property. '
'Note that this event is fired once for each property from the array returned by the GetCustomProperties() method. '
'Therefore you need to implement a logic that returns a separate object for each property. '
End Function
Public Sub RestoreValue(customPropertyInfo As CustomPropertyInfo, context As Object, value As Object)
'Use the value argument to get the persisted settings. '
'Apply these settings on the context object as it represents the persisted component '
End Sub
End Class
Next, you need to register the SampleCustomPropertyProvider in the application.
Example 3: Register the SampleCustomPropertyProvider class
ServiceProvider.RegisterPersistenceProvider<ICustomPropertyProvider>(typeof(SampleControl), new SampleCustomPropertyProvider());
ServiceProvider.RegisterPersistenceProvider(Of ICustomPropertyProvider)(GetType(SampleControl), New SampleCustomPropertyProvider())
Please note that the SampleControl type is simply an example and instead you need to define the type of the component for which the SampleCustomPropertyProvider is built.
You can find examples of ICustomPropertyProvider implementations in the PersistenceFramework demos. Open the UI for WPF demos and search for the following examples:
- GridView Serializaiton
- Docking Serializaiton
IAttachedPropertyProvider
This IAttachedPropertyProvider interface should be implement when you want to persist custom attached properties. It exposes the following method:
- GetAttachedPropertyTypeProviders(): This method should return an array of Type objects to represent the list of attached properties that have to be persisted by the PersistenceFramework.
Example 4: Implement IAttachedPropertyProvider interface
public class CustomAttachedProvider : IAttachedPropertyProvider
{
public Type[] GetAttachedPropertyTypeProviders()
{
return new Type[]
{
};
}
}
IPropertyProvider
This IPropertyProvider interface should be implement when you want to control which properties should be saved.
- GetProperties(): this method should return an array of PropertyInfo objects to represent the list of properties that have to be persisted by the PersistenceFramework.
Example 5: Implement IPropertyProvider interface
public class CustomPropertyProvider : IPropertyProvider
{
public PropertyInfo[] GetProperties()
{
List<PropertyInfo> properties = new List<PropertyInfo>();
var allProperties = typeof(RadGridView).GetProperties();
foreach (PropertyInfo item in allProperties)
{
if (item.Name == "Width" || item.Name == "Height")
{
properties.Add(item);
}
}
return properties.ToArray();
}
}
IPropertyValidatorProvider
By implementing this interface you can validate if a property should be saved or not.
- IsValid(): This method return true or false if a property should be persist.
Example 6: Implement IPropertyValidatorProvider interface
public class PropertyValidatorProvider : IPropertyValidatorProvider
{
public bool IsValid(string propertyName, Type propertyType, object context, object value)
{
return true;
}
}
Only one validator for given type should be register.
ITypeConverterProvider
The ITypeConverterProvider interface should be implement in order to convert a values or properties.
- GetTypeConverterType(): This method return the type of the TypeConverter.
Example 7: Implement ITypeConverterProvider interface
public class TypeProvider : ITypeConverterProvider
{
public Type GetTypeConverterType()
{
return typeof(CustomTypeConverter);
}
}
public class CustomTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return base.ConvertTo(context, culture, value, destinationType);
}
}