Freigeben über


Generic control creation.

I've been doing a lot of coding lately that utilize the features of the C# 2.0  and 3.0 language enhancements such as generics, Func delegates, anonymous types etc... And then it hit me that we are still using the old and clumsy coding style when developing for WinForms - creating controls, assinging properties etc...  What if we could do something like that:        

Button clickButton = this.AddControl<Button>(c => new Button()

{

       Name = "button",

       Text = "Click Me",

       Location = new Point(100, 200),

       Font = c.Font

});

 

In the code above we create an instance of the Button, set it's properties and add it to the parent's controls collection - all in one line of code! Do you like it? I do. Somehow it feels much cleaner and nicer than this:

  

Button clickButton = new Button();

clickButton.Name = "button";

clickButton.Text = "Click Me";

clickButton.Location = new Point(100, 200);

clickButton.Font = this.Font;

this.Controls.Add(clickButton); 

So here is how the code for the "Hello World" sample Form would look like:

 

public partial class Form1 : Form

{

    public Form1()

    {

        InitializeComponent();

        

        // Create button and add it to the Form's controls collection

        Button clickButton = this.AddControl<Button>(c => new Button()

        {

            Name = "button",

            Text = "Click Me",

            Location = new Point(100, 200),

            Font = c.Font

        });

        // Hook up into the click event

        clickButton.Click += new EventHandler(clickButton_Click);

        // Create label

        this.AddControl<Label>(c => new Label()

        {

            Name = "labelHello",

            Location = new Point(100, 240)

        });

         

    }

    void clickButton_Click(object sender, EventArgs e)

    {

        // Assign the value to the Text property of the label

  this.GetControl<Label>("labelHello").Text = "Hello world.";

    }

}

So what do we need to be able to write the code like this? All we need to do is to add the following ControlExtension class:

 

public static class ControlExtension

{

     public static T AddControl<T>(this Control parent,

Func<Control, T> build)

     {

         T control = build(parent);

         parent.Controls.Add(control as Control);

         return control;

     }

     public static Control GetControl(this Control parent, string name)

     {

         return parent.Controls[name];

     }

     public static T GetControl<T>(this Control parent, string name)

where T : Control

     {

         return parent.Controls[name] as T;

     }

 }

In this class all we do is just create a few extension methods for the Control. That's it folks.

 

And by the way, this code works on both desktop (.NET 3.5) and device side (.NET CF 3.5)

 

Enjoy :)

Comments

  • Anonymous
    January 10, 2009
    Very neat, especially the AddControl extension! Though I would prefer to leave the controls declaration out of the form’s constructor instead of using the GetControl extension, so the compiler will be able to trace errors and for better performance. Interesting as always. Thx.

  • Anonymous
    January 18, 2009
    Hi Alex, Great stuff. I ran into a hitch with the Compact Framework with the WinForms implementation not providing a string indexer for Controls, so I used this instead(example from GetControl): return parent.Controls.OfType<Control>().SingleOrDefault(c => c.Name == name); That works OK for me but let me know if there's another approach that's preferred (I'm very partial to LINQ to Objects and likely to use/misuse it whenever an excuse arises).

  • Anonymous
    January 21, 2009
    Hi Kevin, I would change it like this: return parent.Controls.Cast<Control>().SingleOrDefault(c => c.Name == name); -Alex

  • Anonymous
    January 23, 2009
    The comment has been removed

  • Anonymous
    January 24, 2009
    Even though I don't work in the product group, I am pretty sure that Windows Mobile dev is still alive and kicking :)

  • Anonymous
    January 26, 2009
    Continuing on this mental exercise that I started in my last post . In this post I started throwing some

  • Anonymous
    February 16, 2009
    Since posting a few of my last ideas , my brain has been running a few background threads on how else