Tuesday 14 August 2012

Telerik WPF RadDatePicker, XML serialization, handling null values

To support blank values, an instance of the RadDatePicker must be bound to a value of DateTime? (nullable) type. Otherwise wiping out control's value does not change the bound value at all. Even more, it displays a nasty red border around the control.

If a bound value is a member of class intended to be serialized and de-serialized, it should be attributed in a specific way.

a) Apparently a member of DateTime? type stored in XML attribute, but only XML element should be used for that. An example is below.


private DateTime? _startDate;


[XmlElementAttribute(
    Form = System.Xml.Schema.XmlSchemaForm.Unqualified, 
    IsNullable = true)]
public DateTime? StartDate
{
    get
    {
        return this._startDate;
    }

    set
    {
        this._startDate = value;
        this.OnPropertyChanged("StartDate");
    }
}


The IsNullable parameter has to be either omitted or set to True.

b) Optionally you may include ShouldSerialize method as below. Note that the method's name must end with the member's name.


public bool ShouldSerializeStartDate()
{
    return this.StartDate.HasValue;
}


With such method present, an element with null value will be completely removed from serialization output. 

With no ShouldSerialize method implemented, such element will stay in the output but will hold no value.

<SampleEntity>
<StartDate xsi:nil="true" />
<EndDate>2012-07-31T00:00:00</EndDate>
</SampleEntity>

This post I conclude with two generic serialization routines.

public static string SerializeInstance<T>(this T instance)
{
    var serializer = new XmlSerializer(typeof(T));

    var stringBuilder = new StringBuilder();

    var settings = new XmlWriterSettings
    {
        ConformanceLevel = ConformanceLevel.Document,
        OmitXmlDeclaration = true
    };


    using (var writer = XmlWriter.Create(stringBuilder, settings))
    {
        serializer.Serialize(writer, instance);
        return stringBuilder.ToString();
    }
}

public static T DeserializeInstance<T>(string content)
{
    var serializer = new XmlSerializer(typeof(T));

    using (var reader = new StringReader(content ?? string.Empty))
    {
        var instance = (T)serializer.Deserialize(reader);
        return instance;
    }
}



No comments:

Post a Comment