Reputation: 6152
I have a DGV bound to a list of objects. This works fine except that one of the object properties is boolean and therefore displays as a checkbox but I would prefer a simple yes/no text field instead. I've considered adding an additional column and populating with the appropriate string based on the boolean value but this seems a little over the top. Is there an easier way?
The DGV is read-only.
Upvotes: 1
Views: 7710
Reputation: 74730
A useful way to do this is to use a DataGridViewComboBoxColumn to decode your boolean to whatever string you want; it retains the ability to edit the value too and can even provide shortcuts for the user if you ensure that your list of display values has a differnt initial letter (the user can focus the cell and press the single key on the keyboard to alter the combo selection).
Combo columns aren't just restricted to booleans - any fixed list of values, lookups, enums etc are good a candidate. This is how you might wire up a boolean; it uses a Tuple of string/bool as the backing store for the combo to look in/look up from:
dataGridView1.Columns.Add(new DataGridViewComboBoxColumn() {
DataPropertyName = "NameOfYourBoolColumnInYourDataTableThatTheGridIsBoundTo";
DisplayMember = "Item1", //the string in the Tuple
ValueMember = "Item2", //the bool in the Tuple
DataSource = new List<Tuple<string, bool>>() { //the list of Tuples
Tuple.Create("Yeah baby", true),
Tuple.Create("Noooo way", false)
}
});
This grid will now show a combo where it once showed a checkbox, and editing the combo will change the boolean value in your main datatable. The values that show in the table are the strings "Yeah baby" and "Nooo way" rather than true/false but in the back end it I the true false that is read from the main table's bool column, and written back to it
If your datagridview is designed in the forms designer, the easiest thing would probably be to add a DispVal table to a strongly typed dataset, then it becomes available as a "project list instance" in the picker that lets you choose the datasource for the combo column
Upvotes: 1
Reputation: 770
As mentioned above it seems to be impossible to change the visual appearance of boolean values in a data bound scenario. Even DataGridViewCellStyle.FormatProvider does not work correctly with types like System.Int32, System.Int64, System.Decima, etc.
Therefore I found a workaround which works for me. Probably it is not the best solution but currently it fits my needs. I handle the DataGridView.ColumnAdded event and replace DataGridViewCheckBoxColumn with DataGridViewTextBoxColumn. Afterwards I use CellFormating event (recommended by Microsoft, see links above) to format source data.
private DataGridViewTextBoxColumn textBoxColumn = null;
void _dataGrid_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
// Avoid recursion
if (e.Column == textBoxColumn) return;
DataGridView gridView = sender as DataGridView;
if (gridView == null) return;
if( e.Column is DataGridViewCheckBoxColumn)
{
textBoxColumn = new DataGridViewTextBoxColumn();
textBoxColumn.Name = e.Column.Name;
textBoxColumn.HeaderText = e.Column.HeaderText;
textBoxColumn.DataPropertyName = e.Column.DataPropertyName;
gridView.Columns.Insert(e.Column.Index, textBoxColumn);
gridView.Columns.Remove(e.Column);
}
}
void _dataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewColumn col = _dataGrid.Columns[e.ColumnIndex];
try
{
if ( col.Name == "IsMale")
{
bool isMale = Convert.ToBoolean(e.Value);
e.Value = isMale ? "male" : "female";
}
}
catch (Exception ex)
{
e.Value = "Unknown";
}
}
Upvotes: 5
Reputation: 53593
Edit the column that displays the boolean so the ColumnType property = DataGridViewTextBoxColumn.
The column will now display the strings True/False.
Make this change in the designer:
In the designer, right click the DGV.
On the popup menu, select 'Edit Columns...' The Edit Columns dialog will appear.
In the Edit Columns dialog, pick your column on the left and find the properties (including ColumnType) on the right.
You can set the ColumnType programmatically when a column is being added to your DGV:
DataGridViewColumn column = new DataGridViewColumn();
DataGridViewCell cell = new DataGridViewTextBoxCell();
column.CellTemplate = cell;
dgv.Columns.Add(column);
Code from MSDN.
Upvotes: 0
Reputation: 6152
It looks like this is not possible so I cheated. I added a read-only property to my business object which returns a string based on the boolean property. I just hid the boolean column in the DGV and displayed the string property.
Upvotes: 3