<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Simon&#039;s Wonder World &#187; DataBinding</title>
	<atom:link href="http://blog.simonstahl.com/tag/databinding/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.simonstahl.com</link>
	<description>Just another European geek in Silicon Valley</description>
	<lastBuildDate>Tue, 19 Apr 2011 22:01:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>An easy way to revert changes in Object data</title>
		<link>http://blog.simonstahl.com/2009/12/14/an-easy-way-to-revert-changes-in-object-data/</link>
		<comments>http://blog.simonstahl.com/2009/12/14/an-easy-way-to-revert-changes-in-object-data/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 23:43:53 +0000</pubDate>
		<dc:creator>Simon</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Clone]]></category>
		<category><![CDATA[DataBinding]]></category>
		<category><![CDATA[DataContext]]></category>
		<category><![CDATA[INotifyPropertyChanged]]></category>
		<category><![CDATA[Model View Control]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[PropertyChangedEventHandler]]></category>
		<category><![CDATA[Serializable]]></category>
		<category><![CDATA[SerializationException]]></category>

		<guid isPermaLink="false">http://blog.simonstahl.com/?p=42</guid>
		<description><![CDATA[A quite common problem in an MVC GUI is the need to revert changes in the model made by the user. Let&#8217;s say you create a UI where the user can modify some fields that are bound to a model object. After the user already did some changes, he recognizes that he entered some wrong [...]]]></description>
			<content:encoded><![CDATA[<p>A quite common problem in an <strong>MVC </strong>GUI is the need to revert changes in the model made by the user. Let&#8217;s say you create a UI where the user can modify some fields that are bound to a model object. After the user already did some changes, he recognizes that he entered some wrong data and wants to cancel the editing. So what now? The data is already written into the model.</p>
<p>The easiest way to revert this changes is obviously to let the user work with a copy of the real data object. So let&#8217;s add a clone method to the model and mark it as Serializable.<span id="more-42"></span></p>
<h2>Model with Clone() method</h2>
<pre class="brush:c#">[Serializable]
public abstract class PersonModel {

    public string Name { get; set; }
    public string FirstName { get; set; }
    public int Age { get; set; }

    public PersonModel Clone() {
        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream) {
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            return (PersonModel)formatter.Deserialize(stream);
        }
    }
}</pre>
<p>We now just bind the copy of the object to the view:</p>
<pre class="brush:c#">myView.DataContext = person.Clone();</pre>
<p>This copy can easily be dropped in case the user cancels the editing. In case he saves the<br />
changes, you can just replace the original object with the copy.</p>
<p>One problem I ran in it was, that I normally implement the <strong>INotifyPropertyChanged </strong>interfaces to my models to inform the view about changes in the model. Unfortunately the <strong>PropertyChangedEventHandler </strong>contained in this interface causes a nasty SerializationException because the Class PropertyChangedEventManager is not marked as Serializable.</p>
<p><em><strong>System.Runtime.Serialization.SerializationException was caught</strong><br />
Message=&#8221;Type &#8216;System.ComponentModel.PropertyChangedEventManager&#8217; in Assembly &#8216;WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&#8242; is not marked as serializable.&#8221;</em></p>
<p>The easiest way to work around this problem is to just exclude the <strong>PropertyChangedEventHandler </strong>from the serialization.</p>
<h2>Clonable Model that implements INotifyPropertyChanged</h2>
<pre class="brush:c#">[Serializable]
public abstract class PersonModel : INotifyPropertyChanged {
    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    private string name;
    private string firstName;
    private int age;

    public string Name {
        get { return name; }
        set { name = value; OnPropertyChange(); }
    }
    public string FirstName {
        get { return firstName; }
        set { firstName = value; OnPropertyChange(); }
    }
    public int Age {
        get { return age; }
        set { age = value; OnPropertyChange(); }
    }

    public PersonModel Clone() {
        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream) {
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            return (PersonModel)formatter.Deserialize(stream);
        }
    }

    protected void OnPropertyChange() {
        string propName = new StackFrame(1).GetMethod().Name.Replace("set_", "");
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}</pre>
<p>In this way everything works fine and you have hopefully one problem less to care about&#8230;</p>
<p>Happy DataBinding <img src='http://blog.simonstahl.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.simonstahl.com/2009/12/14/an-easy-way-to-revert-changes-in-object-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

