Best Design Pattern for Coupling User Interface Components and Data Structures
- by szahn
I have a windows desktop application with a tree view. Due to lack of a sound data-binding solution for a tree view, I've implemented my own layer of abstraction on it to bind nodes to my own data structure.
The requirements are as follows:
Populate a tree view with nodes that resemble fields in a data structure.
When a node is clicked, display the appropriate control to modify the value of that property in the instance of the data structure.
The tree view is populated with instances of custom TreeNode classes that inherit from TreeNode. The responsibility of each custom TreeNode class is to (1) format the node text to represent the name and value of the associated field in my data structure, (2) return the control used to modify the property value, (3) get the value of the field in the control (3) set the field's value from the control.
My custom TreeNode implementation has a property called "Control" which retrieves the proper custom control in the form of the base control.
The control instance is stored in the custom node and instantiated upon first retrieval. So each, custom node has an associated custom control which extends a base abstract control class.
Example TreeNode implementation:
//The Tree Node Base Class
public abstract class TreeViewNodeBase : TreeNode {
public abstract CustomControlBase Control { get; }
public TreeViewNodeBase(ExtractionField field)
{
UpdateControl(field);
}
public virtual void UpdateControl(ExtractionField field)
{
Control.UpdateControl(field);
UpdateCaption(FormatValueForCaption());
}
public virtual void SaveChanges(ExtractionField field)
{
Control.SaveChanges(field);
UpdateCaption(FormatValueForCaption());
}
public virtual string FormatValueForCaption()
{
return Control.FormatValueForCaption();
}
public virtual void UpdateCaption(string newValue)
{
this.Text = Caption;
this.LongText = newValue;
}
}
//The tree node implementation class
public class ExtractionTypeNode : TreeViewNodeBase
{
private CustomDropDownControl control;
public override CustomControlBase Control
{
get
{
if (control == null)
{
control = new CustomDropDownControl();
control.label1.Text = Caption;
control.comboBox1.Items.Clear();
control.comboBox1.Items.AddRange(
Enum.GetNames(
typeof(ExtractionField.ExtractionType)));
}
return control;
}
}
public ExtractionTypeNode(ExtractionField field)
: base(field) {
}
}
//The custom control base class
public abstract class CustomControlBase : UserControl {
public abstract void UpdateControl(ExtractionField field);
public abstract void SaveChanges(ExtractionField field);
public abstract string FormatValueForCaption();
}
//The custom control generic implementation (view)
public partial class CustomDropDownControl : CustomControlBase {
public CustomDropDownControl()
{
InitializeComponent();
}
public override void UpdateControl(ExtractionField field)
{
//Nothing to do here
}
public override void SaveChanges(ExtractionField field)
{
//Nothing to do here
}
public override string FormatValueForCaption()
{
//Nothing to do here
return string.Empty;
}
}
//The custom control specific implementation
public class FieldExtractionTypeControl : CustomDropDownControl {
public override void UpdateControl(ExtractionField field)
{
comboBox1.SelectedIndex =
comboBox1.FindStringExact(field.Extraction.ToString());
}
public override void SaveChanges(ExtractionField field)
{
field.Extraction = (ExtractionField.ExtractionType)
Enum.Parse(typeof(ExtractionField.ExtractionType),
comboBox1.SelectedItem.ToString());
}
public override string FormatValueForCaption()
{
return string.Empty;
}
The problem is that I have "generic" controls which inherit from CustomControlBase. These are just "views" with no logic. Then I have specific controls that inherit from the generic controls. I don't have any functions or business logic in the generic controls because the specific controls should govern how data is associated with the data structure.
What is the best design pattern for this?