<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>Deep Ena</title>
    <link rel="self" type="application/xml" href="http://geekswithblogs.net/panpra/Atom.aspx" />
    <subtitle type="html"> </subtitle>
    <id>http://geekswithblogs.net/panpra/Default.aspx</id>
    <author>
        <name>panpra</name>
        <uri>http://geekswithblogs.net/panpra/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 0.0.0.0">Subtext</generator>
    <updated>2011-03-16T04:26:12Z</updated>
    <entry>
        <title>Two-way data binding in ASP.NET - Part 1</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/panpra/archive/2010/02/08/aspnetdatabinding-part1.aspx" />
        <id>http://geekswithblogs.net/panpra/archive/2010/02/08/aspnetdatabinding-part1.aspx</id>
        <published>2010-02-08T09:22:43-06:00:00</published>
        <updated>2011-03-16T04:24:45Z</updated>
        <summary type="html">In this post I am going to talk about modifying object container data source (OCDS) to support two-way hierarchical data binding </summary>
        <content type="html">&lt;div&gt;&lt;span style="font-size: 9pt"&gt;Data binding is a powerful paradigm to reduce boilerplate code. In this post I am going to talk about a way to convert Object Container Data Source (OCDS) to support hierarchical two-way data binding with &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;In a recent project I worked on, we used Web Client Software Factory (WCSF) extensively to get a handle on the complexity of the web application. I know this is pretty old stuff when compared to exciting stuff like Silverlight and ASP.NET MVC. Two-way data binding in webforms is quite tricky when dealing with some edge conditions and complex workflows. Dynamic Data is one of the other technologies which tries to make binding less painful. But because of the limitations we had with our environment, we had to use regular Web Forms with web controls.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;One of the rationales behind using WCSF was to adhere to MVP with IoC to make the web application more testable. Our main goal was to use two-way data binding to keep the codebehind clean and simple. But, the moment we started actual development with OCDS &amp;amp; FormView  we realized that it was possible to read off of the properties of an object deep in hierarchy (Eval), but you cannot write back(Bind) values to the same object. So, out of the box OCDS supports two-way binding (Bind) only to the properties at first level. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;I don’t know if anyone has pushed the limits of two-way binding this far as we did in our project but we have encountered some significant problems with validation, retaining state if validation fails, hierachical data binding with complex objects (as against to POCO), certain edge scenarios on a form which doesn’t fall into data binding control etc. I will talk about each one of these scenarios later in a different post.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;  &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;So we had to modify OCDS (WebControls.sln in WCSF source) to support hierarchical data binding to a complex object. We solved it by using something similar to &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.itypedlist.aspx"&gt;ITypedList &lt;/a&gt;implementation.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;span style="color: blue; font-size: 10pt"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;TypedListImplementation&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;PropertyDescriptorCollection&lt;/span&gt; GetItemProperties(&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt; type, &lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt;[] properties, &lt;span style="color: blue"&gt;string&lt;/span&gt; domainMarkerType)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;var&lt;/span&gt; descriptorCollection = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;PropertyDescriptorCollection&lt;/span&gt;(properties);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;&amp;gt; tracker = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;&amp;gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// add the base type to be traversed.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            tracker.Push(type);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-indent: 0.5in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span style="color: green; font-size: 10pt"&gt;// traverse through the object type hierarchy&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;foreach&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; descriptor &lt;span style="color: blue"&gt;in&lt;/span&gt; &lt;span style="color: #2b91af"&gt;TypeDescriptor&lt;/span&gt;.GetProperties(type, &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Attribute&lt;/span&gt;[] { &lt;span style="color: #2b91af"&gt;BrowsableAttribute&lt;/span&gt;.Yes }))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                AddChildDescriptor(descriptor, descriptorCollection, domainMarkerType, tracker);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;...&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;Traverse the object hierarchy using a stack to avoid infinite loop.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue; font-size: 10pt"&gt;private&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; AddChildDescriptor(&lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; descriptor, &lt;span style="color: #2b91af"&gt;PropertyDescriptorCollection&lt;/span&gt; descriptorCollection,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;string&lt;/span&gt; domainMarkerType, &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;&amp;gt; tracker)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: #2b91af"&gt;Type&lt;/span&gt; markerInterfaceType = descriptor.PropertyType.GetInterface(domainMarkerType);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// return if the descriptor type doesn't implement domain marker interface.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt; (markerInterfaceType == &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                descriptorCollection.Add(descriptor);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;foreach&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; childDescriptor &lt;span style="color: blue"&gt;in&lt;/span&gt; childDescriptors)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                &lt;span style="color: green"&gt;// recurse through the whole hierarchy&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                AddChildDescriptor(&lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CustomPropertyDescriptor&lt;/span&gt;(descriptor, childDescriptor), descriptorCollection, domainMarkerType, tracker);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;...&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;Create a custom property descriptor to capture the parent-child hierarchy.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue; font-size: 10pt"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CustomPropertyDescriptor&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    &lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; _parent;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    &lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; _child;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    &lt;span style="color: blue"&gt;public&lt;/span&gt; CustomPropertyDescriptor(&lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; parent, &lt;span style="color: #2b91af"&gt;PropertyDescriptor&lt;/span&gt; child)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        : &lt;span style="color: blue"&gt;base&lt;/span&gt;(child)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        _parent = parent;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        _child = child;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; Name&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        &lt;span style="color: blue"&gt;get&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;return&lt;/span&gt; _parent.Name + &lt;span style="color: #a31515"&gt;"."&lt;/span&gt; + &lt;span style="color: blue"&gt;base&lt;/span&gt;.Name;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;    }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;...&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;Domain marker type property is exposed on&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: #2b91af"&gt;ObjectContainerDataSourceView&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 9pt"&gt; .&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue; font-size: 10pt"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; DomainMarkerType&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;get&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: blue"&gt;string&lt;/span&gt;.IsNullOrEmpty(_domainMarkerType))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                    &lt;span style="color: blue"&gt;throw&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Domainmarkertype needs to be set."&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; _domainMarkerType; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;Modified the calls to TypeDescriptor.GetProperties() to use TypeListImplementation.GetItemProperties(…) .&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;This implementation would essentially convert the OCDS to support the hierarchical two-way binding. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size: 9pt"&gt;In Part 2 of this post I am going to talk about the problems we encountered while using two-way binding.&lt;/span&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;&lt;img src="http://geekswithblogs.net/panpra/aggbug/137855.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/panpra/comments/137855.aspx</wfw:comment>
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/panpra/comments/commentRss/137855.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/panpra/services/trackbacks/137855.aspx</trackback:ping>
    </entry>
</feed>
