views:

661

answers:

3

I'd like to create a derived control from System.Windows.Forms.ComboBox that is bound to a list of objects that I retrieve from the database. Idea is other developers can just drop this control on their form without having to worry about the datasource, binding, unless they want to.

I have tried to extend combobox and then set the DataSource, DisplayMember, and ValueMember in the constructor.

public class CustomComboBox : ComboBox
{
    public CustomComboBox() 
    {
        this.DataSource = MyDAL.GetItems(); // Returns List<MyItem>
        this.DisplayMember = "Name";
        this.ValueMember = "ItemID";
    }
}

Works when I run, but throws a lot of errors in Visual Studio's once it's added to any form. The error I get is:

"Code generation for property 'Items' failed. Error was: 'Object reference not set to an instance of an object"

What's the correct way to accomplish this (C#, Winforms, .NET 2.0+)?

+5  A: 

The problem is that the designer actually does some compilation and execution in a slightly different context than normally running the program does.

In the constructor, you can wrap your code in:

if (!DesignMode)
{
  //Do this stuff
}

That will tell the designer to not run any of your initialization code while it is being designed.

toast
A: 

My usual comment here - DesignMode is not reliable in any situation other than if the control is placed directly on a design surface - i.e. if the control is placed on another control, DesignMode is not true even if you are in design mode. I have found NO reliable way to tell if you are in design mode - especially with inherited controls. Even variants using Site are not reliable if the control is inherited from a non-visual control (e.g. Common Dialog).

See http://keyofdflat.livejournal.com/5407.html (make sure to read the last comment).

kpollock
+1  A: 

DesignMode property doesn't work in a constructor. From googling for a while, found this LicenseManager thing.

if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
    // Do your database/IO/remote call
}

However LicenseManager only works in constructors. For eventhandlers use DesignMode.

Source: http://dotnetfacts.blogspot.com/2009/01/identifying-run-time-and-design-mode.html

Another reference: http://weblogs.asp.net/fmarguerie/archive/2005/03/23/395658.aspx

debugme
That's kind of weird, but I did learn something. So, I call it a win.
toast