I made a custom DataGridView component which has a standard DataGridViewImageColumn inside. A new property changes the visibility of the column when i don\'t need in in a pa
The control is acting as expected.
Reason
You added a column in constructor, then the designer serializes the column. Then you run the application and it adds a column in constructor. So you have 2 columns. And this continues this way and is not limited to 2 columns. Even you don't need to build and run, it's enough to open the form which contains the grid and make a small change in form and save it. A new column is born!
Solutions
Based on your requirements, to solve the problem, you can consider these options:
Check if the control is in design mode, then don't add the column and add it only at run-time.
You can check if the control contains an existing such image column then don't add another one. You can make the column unique by it's type of some properties.
You can create a custom designer for the control and put the code of adding the column in initialization of control. This way the code only runs firs time you add the control to the form.
Some notes about solutions
Choosing between solutions is completely based on your requirements and all options are available. But consider these notes about solutions:
About the 1st solution, don't use DesignMode
property because it doesn't work in constructor. Instead perform check this way:
if (System.ComponentModel.LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
//The control is not in design mode, add the column here.
}
About the 2nd solution, for example it's enough to add a new MyCustomImageColumn
type and only check existence of a column of type MyCustomImageColumn
and if it exists, don't add another one, because one of them is enough.
DataGridView
has its own Designer names DataGridViewDesigner
which is internal and you can not inherit from it and if you only create a designer because of this requirement you will miss some features of original designer. Probably you can workaround this or even create a ToolBoxItem
instead of a designer, but you don't need it. The option is here to make the answer more complete and useful for future readers for such cases.People have fought against this issue for years, but as Reza stated this is expected behavior - hence why it's never been "fixed". There's a lengthy MSDN forum thread discussing this very issue. Among numerous failed solution proposals, most of the successful suggestions provided by Reza are alluded to in some degree.
In the above mentioned thread, a fourth suggestion first proposed by user CoolDadTx is to wrap the DataGridView
in a UserControl
and then add the column that way. Further reasoning:
Using Inheritance for setting properties is a bad practice, inheritance should be used for adding functionality or overriding the behavior of current one.
If you want to make this kind of customization you should use usercontrol instead or using a shared function which configure you gridviewproperty on runtime.
-- Marco Guignard, July 17, 2014
The advantage is that the UserControl
will only add properties to the designer that you've explicitly exposed. Therefore your added column(s) will not be duplicated. Although it is not as concise as a DesignTime
if-statement, usage might look like the following:
public class CustomControl : UserControl
{
private DataGridViewImageColumn EditStatusIcons;
public DataGridView DGV;
private bool hasIcons = true;
public bool HasIcons
{
get { return this.hasIcons; }
set
{
if (this.DGV.Columns["EditStatusIcons"] == null) return;
this.dataGridView1.Columns["EditStatusIcons"].Visible = value;
this.hasIcons = value;
}
}
public CustomDataGridView()
{
this.EditStatusIcons = new System.Windows.Forms.DataGridViewImageColumn();
this.EditStatusIcons.HeaderText = "";
this.EditStatusIcons.Name = "EditStatusIcons";
this.DGV= new DataGridView();
this.DGV.Dock = DockStyle.Fill;
this.DGV.Columns.Add(this.EditStatusIcons);
this.Controls.Add(this.DGV);
}
}