Click here to Skip to main content
Click here to Skip to main content

Automatic Dialogs in .NET

By , 13 Apr 2009
Rate this:
Please Sign up or sign in to vote.

autodlg.jpg

Introduction

The following tutorial describes how to use the System.Attribute class for building dialogs automatically.

Background

For this tutorial, some knowledge on Reflection and the creation of Windows Forms in .NET is helpful.

Using the code

Assuming you have a class for storing data, e.g., a customer dataset, and you want to provide a dialog for user interaction. The method described in this tutorial gives you a way to provide a dialog simply without programming one, but by defining Attributes for every property of the class that you wish to be edited.

Creating automatic dialogs is simply a matter of identifying the need for specific controls of a class. This is followed by creating and arranging these controls on a Windows form.

As an example, I would like to discuss a class called "Customer", which defines the structure of a Customer dataset. If it has a property name of type string, it is safe to say, you would use a TextBox to display and modify its value. This also works for the DateTime data type and the DateTimePicker control, or bool and CheckBox.

A most simple version of an automatic dialog could use Reflection to identify the properties of a class and then create and arrange the controls depending on the data types of the properties. Reflection would also be used to invoke the get methods for filling the controls initially and the set methods for saving the modified fields. We want to use custom attributes to define the class properties a little more exactly than just through their data types.

Example: The Customer class with the properties:

  • ID (Integer)
  • Name (String)
  • Active (Boolean)
  • DateOfBirth (DateTime)

Now, we describe these properties a little further using an attribute called EditField:

public class Customer
{
    private int id;
    private string name;
    private DateTime dob;
    private bool active;

    [EditField("Custom #")]
    public int ID
    {
        get { return this.id; }
    }

    [EditField("Name")]
    public string Name
    {
        get { return this.name; }
        set { this.name = value; }
    }

    [EditField("Active")]
    public bool Active
    {
        get { return this.active; }
        set { this.active = value; }
    }

    [EditField("DoB")]
    public DateTime DateOfBirth
    {
        get { return this.dob; }
        set { this.dob = value; }
    }
}

In this tutorial, we only consider the possibility of labeling controls created on the dialog with a special name.

So, we use a simple attribute EditField with only one property, Name:

public class EditField : System.Attribute
{
    private string name;
    
    public EditField(string name)

    {
        this.name = name; 
    }
    
    public string Name
    {
        get { return this.name; }
    }
}

Now, we construct an object of a dialog class called DlgEdit. This dialog gets the type or an instance of Customer as the parameter.

It can now loop over the properties of the Customer class with following foreach-loop:

public DlgEdit(Type t)
{
    foreach(PropertyInfo info in t.GetProperties())
    { 
        //...

    }
}

The PropertyInfo object contains information of the data type, and most importantly, a method for reading custom attributes:

We can now loop over all the attributes using:

foreach (EditField editField in 
         info.GetCustomAttributes(typeof(EditField), true) 
{ 
    //...
}

For this simple example, we only need to create a control for the found data type of the property and a label with the text defined in editField.Name, which would be the parameter we delivered by defining the attributes in the Customer class. The PropertyInfo object also contains the information if you can read and write the property; that means, if you have defined get- or set-accessors. You can use this information to set the the readonly properties (or Enabled) of the created controls, if needed.

The control creation depending on the data type would result in a mapping of data types to control types. So, we would create a TextBox for the String type, and a DateTimePicker for the DateTime type. Since there is no control for Integer or Double data types, we would create a TextBox, but the way of reading and writing the content to and from the control would differ. In the last case, we have to call the int.Parse() method before reading from the TextBox and we would have to call the int.ToString() method before writing it as text to the TextBox.

Reading from an instance of Customer is a matter of using the .NET Reflection classes and the methods with the information of the PropertyInfo object.

object data = t.InvokeMember(info.Name, BindingFlags.GetProperty, 
                             null, this.dataset, null); 

TextBox tb = new TextBox();

tb.Text = (string) data;

Writing to an instance of Customer works the other way around:

t.InvokeMember(info.Name, BindingFlags.SetProperty, null, 
               this.dataset, new object[] { tb.Text }); 

We now need to arrange those controls on the DlgEdit object. Since this is only a matter of setting the Top, Left, Width, and Height properties of the controls and labels, and is up to the individual taste of the programmer, I will discuss this in another article.

This method is open for a lot more possibilities when it comes to customizing your dialog. For example, we might want to display a string not in a TextBox but in a RichTextBox because it is a long text, like a description. In the dialog I created, I have the possibility of grouping the controls in GroupBoxes and/or TabPages.

I also a Help attribute to define a short help text for my class and display it on demand in the DlgEdit form.

Points of interest

This way of creating dialogs has the advantage of saving a lot of time and making your application dialogs look familiar for different classes. Providing user interaction is much easier this way.

I will keep you posted on the development of attribute-based architectures here and on my German project page: http://www.eigene-software.de

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

lithium2709

Germany Germany
IT Student

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHernán Hegykozi29-Oct-12 12:56 
GeneralAttributes aren't localizable PinmemberTiago Freitas Leal24-Feb-10 20:53 
GeneralAttributes ARE localizable PinmemberMember 31458349-Jun-10 20:38 
GeneralAnother way to get-set values of properties Pinmemberkaagle2-Jul-09 22:49 
QuestionWhy a custom EditField attribute? PinmemberSlingBlade21-Apr-09 2:33 
GeneralGreat start PinmemberChrisVaughan20-Apr-09 22:46 
GeneralRe: Great start PinmemberStumproot21-Apr-09 0:56 
NewsFiles Pinmemberpablleaf13-Apr-09 7:24 
GeneralMy vote of 2 PinmemberItay Sagui13-Apr-09 4:20 
GeneralRe: My vote of 2 Pinmemberlithium270913-Apr-09 5:02 
GeneralRe: My vote of 2 PinmemberEddy Vluggen22-Apr-09 0:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140421.2 | Last Updated 13 Apr 2009
Article Copyright 2009 by lithium2709
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid