Geeks With Blogs
Deep Ena
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
 
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.
 
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 & 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.
 
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.
  
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 ITypedList implementation.
 
 
 public class TypedListImplementation
    {
        public static PropertyDescriptorCollection GetItemProperties(Type type, PropertyDescriptor[] properties, string domainMarkerType)
        {
 
            var descriptorCollection = new PropertyDescriptorCollection(properties);
 
            Stack<Type> tracker = new Stack<Type>();
 
            // add the base type to be traversed.
            tracker.Push(type);
// traverse through the object type hierarchy
            foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(type, new Attribute[] { BrowsableAttribute.Yes }))
            {
                AddChildDescriptor(descriptor, descriptorCollection, domainMarkerType, tracker);
            }
 
...
 
Traverse the object hierarchy using a stack to avoid infinite loop.
 
private static void AddChildDescriptor(PropertyDescriptor descriptor, PropertyDescriptorCollection descriptorCollection,
            string domainMarkerType, Stack<Type> tracker)
        {
            Type markerInterfaceType = descriptor.PropertyType.GetInterface(domainMarkerType);
 
            // return if the descriptor type doesn't implement domain marker interface.
            if (markerInterfaceType == null)
            {
                descriptorCollection.Add(descriptor);
                return;
            }
...
 
            foreach (PropertyDescriptor childDescriptor in childDescriptors)
            {
                // recurse through the whole hierarchy
                AddChildDescriptor(new CustomPropertyDescriptor(descriptor, childDescriptor), descriptorCollection, domainMarkerType, tracker);
            }
 
...
 
Create a custom property descriptor to capture the parent-child hierarchy.
 
public class CustomPropertyDescriptor : PropertyDescriptor
{
    PropertyDescriptor _parent;
    PropertyDescriptor _child;
 
    public CustomPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor child)
        : base(child)
    {
        _parent = parent;
        _child = child;
    }
 
    public override string Name
    {
        get
        {
            return _parent.Name + "." + base.Name;
        }
    }
 
...
 
Domain marker type property is exposed on ObjectContainerDataSourceView .
 
public string DomainMarkerType
        {
            get {
                if (string.IsNullOrEmpty(_domainMarkerType))
                    throw new InvalidOperationException("Domainmarkertype needs to be set.");
 
                return _domainMarkerType;
            }
 
 
Modified the calls to TypeDescriptor.GetProperties() to use TypeListImplementation.GetItemProperties(…) .
 
This implementation would essentially convert the OCDS to support the hierarchical two-way binding.
 
In Part 2 of this post I am going to talk about the problems we encountered while using two-way binding.

 

Posted on Monday, February 8, 2010 9:22 AM ASP.NET | Back to top


Comments on this post: Two-way data binding in ASP.NET - Part 1

# re: Two-way data binding in ASP.NET - Part 1
Requesting Gravatar...
Was this for WCSF 2010? Regardless, could you post the actual code files?

Sounds awesome-
Left by Kenneth Scott on Sep 09, 2010 4:41 PM

Your comment:
 (will show your gravatar)


Copyright © panpra | Powered by: GeeksWithBlogs.net