I have extended the ComboBox object, and I would like to assign values to it.

The values will be the same every time, and are not allowed to be changed at runtime.

Here is my object:

public class TimesComboBox: ComboBox
{
    //These items' values are copied from PARC View
    private readonly Dictionary<String, TimeSpan> CONSTANTS = new Dictionary<string, TimeSpan>()
    {
        {"3 H", new TimeSpan(0,3,0,0,0)},
        {"8 H", new TimeSpan(0,8,0,0,0)},
        {"12 H", new TimeSpan(0,12,0,0,0)},
        {"1 D", new TimeSpan(1,0,0,0,0)},
        {"3 D", new TimeSpan(3,0,0,0,0)},
        {"7 D", new TimeSpan(7,0,0,0,0)},
        {"30 D", new TimeSpan(30,0,0,0,0)}
    };

    public TimesComboBox()
        : base()
    {
        DataSource = CONSTANTS.Keys.ToList();
    }

When I run the code, the program throws the error:

Items collection cannot be modified when the DataSource property is set.

And points me to the designer of the form where I am using the TimesComboBox:

// 
// timesComboBox1
// 
this.timesComboBox1.DataSource = ((object)(resources.GetObject("timesComboBox1.DataSource")));
this.timesComboBox1.FormattingEnabled = true;
this.timesComboBox1.Items.AddRange(new object[] {
"3 H",
"8 H",
"12 H",
"1 D",
"3 D",
"7 D",
"30 D"});
this.timesComboBox1.Location = new System.Drawing.Point(72, 55);
this.timesComboBox1.Name = "timesComboBox1";
this.timesComboBox1.Size = new System.Drawing.Size(121, 21);
this.timesComboBox1.TabIndex = 63;

It looks to me like the designer is generating code that is trying to add the items twice. Why is it doing this? I thought that list would only be assigned to the DataSource at runtime, so why is Visual Studio be generating code before that?

有帮助吗?

解决方案

This happens because the constructor of your control class also runs at design time. Which sets the DataSource and the Items properties, their values will be serialized like properties normally are. So you see them back in the Designer.cs code. Usually unseen, not when it generates an exception like it does in this case.

You tell the designer serializer to not do this by using the [DesignerSerializationVisibility] attribute:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ObjectCollection Items {
    get { return base.Items; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new object DataSource {
    get { return base.DataSource; }
    set { base.DataSource = value;  }
}

Adding the [Browsable(false)] attribute also hides the property in the Properties window, very likely you'll want that as well.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top