Showing posts with label DataGridView. Show all posts
Showing posts with label DataGridView. Show all posts

Tuesday, December 7, 2010

DataGridView Custom CheckBox Column

I lately had a need to a checkbox column in a DataGridView, but with custom images (plus, minus and a question mark). DataGridViewCheckBoxColumn images cannot be changed, so I had two options: Customize the OnPaint event, or recreate a new DataGridViewColumn.

I decided to go on the second option. I created a DataGridViewThreeStateCheckBoxColumn class(I prefer long names on abbreviations):

public class DataGridViewThreeStateCheckBoxColumn : DataGridViewImageColumn
{
public DataGridViewThreeStateCheckBoxColumn(ImageList images, bool isThreeState)
{
this.CellTemplate = new DataGridViewThreeStateCheckBoxCell(images, isThreeState, true);
}
}


And a DataGridViewThreeStateCheckBoxCell class:

public enum eState {Unknown = 0, Positive = 1, Negative = 2}
public class DataGridViewThreeStateCheckBoxCell : DataGridViewImageCell
{
private Dictionary StateToImage { get; set; }

private bool IsReadOnly { get; set; }

private eState cellState;
public eState CellState
{
get
{
return cellState;
}
set
{
cellState = value;
this.Value = StateToImage[cellState];
}
}

public DataGridViewThreeStateCheckBoxCell()
{
}

public DataGridViewThreeStateCheckBoxCell(ImageList images, bool isThreeState, bool isReadOnly)
{
StateToImage = new Dictionary { { eState.Unknown, images.Images["question-mark"] }, { eState.Positive, images.Images["plus"] } };
if(isThreeState)
StateToImage[eState.Negative] = images.Images["minus"];
CellState = eState.Unknown;
IsReadOnly = isReadOnly;
}

protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
{
if (IsReadOnly)
return;

// toggle the cell state
CellState = ((eState)(((int)CellState + 1) % StateToImage.Count));

base.OnMouseClick(e);
}
}


In may case I also need a way to notify the parent on state changes, to update a database. I did this by creating an event that the parent was able to register to.

Thursday, July 22, 2010

Overriding ExpandableObjectConverter::GetProperties

Today I was faced with a BrowsableAttribute problem:

I had a collection that I needed to be able to select from a PropertyGrid, but also be able to edit the items and their properties with a DataGridView. I wanted the PropertyGrid to show only the item name in an expandable control and to be able to edit all the items property in the DataGridView.

When using BrowsableAttribute I had a problem that each time I would have to set the value according to the requesting control. I solved this by overriding ExpandableObjectConverter::GetProperties. I went over the PropertyDescriptorCollection and removed each property I didn't want:

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
PropertyDescriptorCollection collection = base.GetProperties(context, value, attributes);
PropertyDescriptor[] final = new PropertyDescriptor[1];
foreach (PropertyDescriptor descriptor in collection)
{
if (descriptor.Name == "ItemName")
final[0] = descriptor;
}
return new PropertyDescriptorCollection(final);
}

Now when binding the list to DataGridView I would see all the properties, and when expanding the list in PropertyGrid I would see only the Item Name Property.