Thursday, August 13, 2009

DataForm Control supporting nested classes


One of the cool things in the toolkit is a new DataForm control. You can give it any object and it will produce a form that will allow you to edit / read your object. However, I noticed that the DataForm, out of the box does not support "auto generation" of fields for nested complex types. This is something that sounds simple to support out of the box, becasue a nested class is really another DataForm control nested within its parent DataForm. Still, when tyring to put a complex type, the Dataform control simply puts a textbox and put the ToString() value of your complex type as its value. Not very useful.

With the help of the UI guy at my work, we found a way to change this limitation and allow for nested UI. I will include the code in this post, but it is mostly testing code and prototype code. You can take it and modify it for your needs.

To do this we creaed a SuperDataForm control



using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Collections.Generic;

namespace ParameterManagement
{
public class SuperDataForm : DataForm
{
List Controls = new List();

public bool CompositeItemIsValid;
public SuperDataForm()
{
this.Loaded += new RoutedEventHandler(SuperDataForm_Loaded);

}

void SuperDataForm_Loaded(object sender, RoutedEventArgs e)
{
if (this.CurrentItem == null)
{
this.CurrentItem = this.DataContext;
}
}

protected override void OnAutoGeneratingField(DataFormAutoGeneratingFieldEventArgs e)
{
// normally change this condition to check it is one of your complex types
// or that it is not a basic type.
if (e.PropertyType == typeof(NestedComplexType))
{
var control = new SuperDataForm();

control.CommandButtonsVisibility = DataFormCommandButtonsVisibility.All;
control.IsReadOnly = false;
Controls.Add(control);
Binding binding = new Binding(e.PropertyName);
binding.Mode = BindingMode.TwoWay;
binding.ValidatesOnExceptions = true;
binding.NotifyOnValidationError = true;
control.SetBinding(DataForm.CurrentItemProperty, binding);
e.Field.IsReadOnly = false;
e.Field.Content = control;
}

}

protected override void OnValidatingItem(System.ComponentModel.CancelEventArgs e)
{
// this is needed to have validation on the children controls
foreach (var control in Controls)
{
if (!control.ValidateItem())
{
CompositeItemIsValid = false;
break;
}
}
}

protected override void OnCurrentItemChanged(EventArgs e)
{

}



}
}


Download Code Here

No comments: