Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Creating a custom DataGridViewColumn with different custom DataGridViewCells per row
 

Creating a custom DataGridViewColumn with different custom DataGridViewCells per row

This might sound like a mammoth task, but bear with me: I'm trying to create custom controls for the DataGridView so I can show very different types of data in the same column but for each row.

I want to end up with something like:
TitleValue
Name [text]
Description [multi-line text]
Financial Data [a small grid of information etc.]

My question is similar to the post here: http://social.msdn.microsoft.com/Forums/en-US/winformsdesigner/thread/63ddb457-f769-44db-87cc-9e88e74929e8
However my cell controls and editor controls need to be very customised.

Has anyone ever done this before without using the cell and column controls already provided by the framework? I've been dabbling all day with no success.
First of all my plan was to make a custom DataGridViewColumn which would only allow a CellType of a custom DataGridViewCell (which I also created).

That failed, so I fell back to making just a custom cell that derrived from DataGridViewCell and attempted to set it to the DataGridView.Row[x].Cell[y], but this didn't work either ("FormattedValueType property of a cell cannot be null", let's ignore that).

Basically, I'm not very clued up on the DataGridView control, or how it manages its cell and columns. Why does it need me to provide a cell type with no parameters in the constructor despite constructing them myself with the correct parameters? :(

Any and all help would be much appreciated!
Software Developer, MCP
Codesleuth  Friday, October 02, 2009 3:58 PM
I hit a breakthrough this morning and got this working quite nicely. I'll see if I can explain:

I created my own DataGridViewColumn called DeliverableAttributeColumn:

public class DeliverableAttributeColumn : DataGridViewColumn
{
    public DeliverableAttributeColumn()
        : base(new DeliverableAttributeCell())
    {

    }

    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if (value != null && !value.GetType().IsAssignableFrom(typeof(DeliverableAttributeCell)))
                throw new InvalidCastException("Must be a DeliverableAttributeCell");
           
            base.CellTemplate = value;
        }
    }
}

I then created my own DataGridViewTextBoxCell called DeliverableAttributeCell:

public class DeliverableAttributeCell : DataGridViewTextBoxCell
{
    private DeliverableTemplateAttributeSearchListItem _templateAttribute;
    private ProjectDeliverableAttributeSearchListItem _deliverableAttribute;

    private Type _editType;

    public DeliverableAttributeCell()
    {
        _editType = typeof(DataGridViewTextBoxEditingControl);
    }

    public void SetAttributes(DeliverableTemplateAttributeSearchListItem templateAttribute,
        ProjectDeliverableAttributeSearchListItem deliverableAttribute)
    {
        _templateAttribute = templateAttribute;
        _deliverableAttribute = deliverableAttribute;

        switch (_templateAttribute.DataType)
        {
            case AttributeDataType.Text:
                _editType = typeof(TextAttributeEditingControl);
                break;
            case AttributeDataType.Decimal:
                _editType = typeof(DecimalAttributeEditingControl);
                break;
            default: throw new NotImplementedException("Data type is not yet implemented.");
        }
    }

    public override Type EditType
    {
        get { return _editType; }
    }

    public DeliverableTemplateAttributeSearchListItem TemplateAttribute
    {
        get { return _templateAttribute; }
        protected set { _templateAttribute = value; }
    }

    public ProjectDeliverableAttributeSearchListItem DeliverableAttribute
    {
        get { return _deliverableAttribute; }
        protected set { _deliverableAttribute = value; }
    }

    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

        switch (_templateAttribute.DataType)
        {
            case AttributeDataType.Text:
                InitializeTextEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
            case AttributeDataType.Decimal:
                InitializeDecimalEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
            default:
                InitializeUnassignedEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
        }
    }

    #region Editing Control Initializers

    private void InitializeUnassignedEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // I hope this isn't needed
        DataGridViewTextBoxEditingControl textEditingControl = this.DataGridView.EditingControl as DataGridViewTextBoxEditingControl;
        if (textEditingControl != null)
        {
            textEditingControl.BorderStyle = BorderStyle.None;
            textEditingControl.Text = (string)this.Value;
        }
    }

    private void InitializeTextEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        TextAttributeSearchListItem textAttribute = (TextAttributeSearchListItem)_templateAttribute;
        TextAttributeEditingControl editingControl = this.DataGridView.EditingControl as TextAttributeEditingControl;
        if (editingControl != null)
        {
            editingControl.BorderStyle = BorderStyle.None;
            editingControl.MaxLength = textAttribute.MaxLength;
            editingControl.Multiline = textAttribute.Multiline;
            editingControl.AcceptsReturn = editingControl.Multiline;

            var value = initialFormattedValue as string;
            editingControl.Text = value == null ? string.Empty : (string)value;
        }
        else
            throw new Exception("There was a problem when attempting to initialize the cell editing control.");
    }

    private void InitializeDecimalEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        DecimalAttributeSearchListItem decimalAttribute = (DecimalAttributeSearchListItem)_templateAttribute;
        DecimalAttributeEditingControl editingControl = this.DataGridView.EditingControl as DecimalAttributeEditingControl;
        if (editingControl != null)
        {
            editingControl.BorderStyle = BorderStyle.None;
            editingControl.MaxLength = 11;
            editingControl.Multiline = false;
            editingControl.AcceptsReturn = false;
            editingControl.TextAlign = HorizontalAlignment.Right;

            var value = initialFormattedValue as string;
            editingControl.Text = value == null ? string.Empty : (string)value;
        }
        else
            throw new Exception("There was a problem when attempting to initialize the cell editing control.");
    }

    #endregion

    protected override object GetFormattedValue(object value,
        int rowIndex, ref DataGridViewCellStyle cellStyle,
        TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter,
        DataGridViewDataErrorContexts context)
    {
        object formattedValue = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
        return formattedValue == null ? string.Empty : (string)formattedValue;
    }
}

This now allows my cell to cleverly detect which data type of the attribute is to be edited and use that when InitializeEditingControl is called. I've only written support so far for the text attribute, which I could have just used a DataGridViewTextBoxEditingControl for, but I needed to understand this in a bit more detail. With a little help from Reflector, I finally got my control to edit and store the value properly:

public class TextAttributeEditingControl: TextBox, IDataGridViewEditingControl
{
    public TextAttributeEditingControl()
    {
        this.TabStop = false;
    }

    #region IDataGridViewEditingControl Members

    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
    {
        this.Font = dataGridViewCellStyle.Font;
        if (dataGridViewCellStyle.BackColor.A < 255)
        {
            // The NumericUpDown control does not support transparent back colors
            Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor);
            this.BackColor = opaqueBackColor;
            this.EditingControlDataGridView.EditingPanel.BackColor = opaqueBackColor;
        }
        else
        {
            this.BackColor = dataGridViewCellStyle.BackColor;
        }
        this.ForeColor = dataGridViewCellStyle.ForeColor;
        this.TextAlign = HorizontalAlignment.Left;
    }

    public DataGridView EditingControlDataGridView { get; set; }

    public object EditingControlFormattedValue
    {
        get { return this.GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting); }
        set { this.Text = (string)value; }
    }

    public int EditingControlRowIndex { get; set; }

    public bool EditingControlValueChanged { get; set; }

    public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
    {
        switch ((keyData & Keys.KeyCode))
        {
            case Keys.Prior:
            case Keys.Next:
                if (!this.EditingControlValueChanged)
                {
                    break;
                }
                return true;

            case Keys.End:
            case Keys.Home:
                if (this.SelectionLength == this.Text.Length)
                {
                    break;
                }
                return true;

            case Keys.Left:
                if (((this.RightToLeft != RightToLeft.No) || ((this.SelectionLength == 0) && (base.SelectionStart == 0))) && ((this.RightToLeft != RightToLeft.Yes) || ((this.SelectionLength == 0) && (base.SelectionStart == this.Text.Length))))
                {
                    break;
                }
                return true;

            case Keys.Up:
                if ((this.Text.IndexOf("\r\n") < 0) || ((base.SelectionStart + this.SelectionLength) < this.Text.IndexOf("\r\n")))
                {
                    break;
                }
                return true;

            case Keys.Right:
                if (((this.RightToLeft != RightToLeft.No) || ((this.SelectionLength == 0) && (base.SelectionStart == this.Text.Length))) && ((this.RightToLeft != RightToLeft.Yes) || ((this.SelectionLength == 0) && (base.SelectionStart == 0))))
                {
                    break;
                }
                return true;

            case Keys.Down:
                {
                    int startIndex = base.SelectionStart + this.SelectionLength;
                    if (this.Text.IndexOf("\r\n", startIndex) == -1)
                    {
                        break;
                    }
                    return true;
                }
            case Keys.Delete:
                if ((this.SelectionLength <= 0) && (base.SelectionStart >= this.Text.Length))
                {
                    break;
                }
                return true;

            case Keys.Return:
                if ((((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == Keys.Shift) && this.Multiline) && base.AcceptsReturn)
                {
                    return true;
                }
                break;
        }
        return !dataGridViewWantsInputKey;
    }

    public Cursor EditingPanelCursor
    {
        get { return Cursors.Default; }
    }

    public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
    {
        return this.Text;
    }

    public void PrepareEditingControlForEdit(bool selectAll)
    {
        if (selectAll)
            this.SelectAll();
        else
            this.SelectionStart = this.Text.Length;
    }

    public bool RepositionEditingControlOnValueChange
    {
        get { return false; }
    }

    #endregion

    private void NotifyDataGridViewOfValueChange()
    {
        this.EditingControlValueChanged = true;
        this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        this.NotifyDataGridViewOfValueChange();
    }
}

Once this was all in place, I tested it with the following code to populate a target DataGridView and see my new column, cell, and editing control in action:

private void PopulateDataGridView(ProjectDeliverableSearchListItem deliverable, DeliverableTemplateSearchListItem template)
{
	// Query lists of attributes used and not yet used
	ProjectDeliverableAttributeSearchList deliverableAttributes = new ProjectDeliverableAttributeSearchList();
	deliverableAttributes.ProjectDeliverableID = deliverable.ID;
	deliverableAttributes.Refresh();

	DeliverableTemplateAttributeSearchList allAttributes = new DeliverableTemplateAttributeSearchList();
	allAttributes.DeliverableTemplateID = template.ID;
	allAttributes.Refresh();

	DeliverableAttributeColumn attributesColumn = new DeliverableAttributeColumn();
	attributesColumn.Name = "Value";

	this.dgvAttributes.Columns.Clear();
	this.dgvAttributes.Columns.Add("Title", "Title");
	this.dgvAttributes.Columns.Add(attributesColumn);

	foreach (var templateAttribute in allAttributes)
	{
		// Find the value that was saved
		var deliverableAttribute = deliverableAttributes.FirstOrDefault(attribute => attribute.DeliverableTemplateAttributeID == templateAttribute.ID);

		// Create the row with the values from the database (if they exist yet)
		int rowIndex = this.dgvAttributes.Rows.Add(templateAttribute.Title, deliverableAttribute != null ? deliverableAttribute.Value : null);
		var row = this.dgvAttributes.Rows[rowIndex];

		// Title cell must be read only
		row.Cells[0].ReadOnly = true;

		// Set the attribute type of the value cell. Cell defaults to "DataGridViewTextBoxEditingControl". See DeliverableAttributeCell.cs
		var deliverableAttributeCell = (DeliverableAttributeCell)row.Cells[1];
		deliverableAttributeCell.SetAttributes(templateAttribute, deliverableAttribute);
	}
}

Since this has some specialized code for my project, I obviously can't go pasting all that stuff too, so I hope you can understand what they do. A "SearchList" is just a query builder that populates itself with multiple values from the database as a special "SearchListItem" type. A deliverable template is a top level template which has an associated designer, and a project deliverable is an instance of a template.


I have some links to similar questions like this, if this doesn't help you:
Since I'm still working on this, I might come up with some problems that I can post here, so add alerts where necessary, and all comments are welcome.
Software Developer, MCP
  • Edited byCodesleuth Monday, October 05, 2009 10:58 AMadded some formatting
  • Marked As Answer byCodesleuth Monday, October 05, 2009 10:59 AM
  •  
Codesleuth  Monday, October 05, 2009 10:56 AM
I hit a breakthrough this morning and got this working quite nicely. I'll see if I can explain:

I created my own DataGridViewColumn called DeliverableAttributeColumn:

public class DeliverableAttributeColumn : DataGridViewColumn
{
    public DeliverableAttributeColumn()
        : base(new DeliverableAttributeCell())
    {

    }

    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if (value != null && !value.GetType().IsAssignableFrom(typeof(DeliverableAttributeCell)))
                throw new InvalidCastException("Must be a DeliverableAttributeCell");
           
            base.CellTemplate = value;
        }
    }
}

I then created my own DataGridViewTextBoxCell called DeliverableAttributeCell:

public class DeliverableAttributeCell : DataGridViewTextBoxCell
{
    private DeliverableTemplateAttributeSearchListItem _templateAttribute;
    private ProjectDeliverableAttributeSearchListItem _deliverableAttribute;

    private Type _editType;

    public DeliverableAttributeCell()
    {
        _editType = typeof(DataGridViewTextBoxEditingControl);
    }

    public void SetAttributes(DeliverableTemplateAttributeSearchListItem templateAttribute,
        ProjectDeliverableAttributeSearchListItem deliverableAttribute)
    {
        _templateAttribute = templateAttribute;
        _deliverableAttribute = deliverableAttribute;

        switch (_templateAttribute.DataType)
        {
            case AttributeDataType.Text:
                _editType = typeof(TextAttributeEditingControl);
                break;
            case AttributeDataType.Decimal:
                _editType = typeof(DecimalAttributeEditingControl);
                break;
            default: throw new NotImplementedException("Data type is not yet implemented.");
        }
    }

    public override Type EditType
    {
        get { return _editType; }
    }

    public DeliverableTemplateAttributeSearchListItem TemplateAttribute
    {
        get { return _templateAttribute; }
        protected set { _templateAttribute = value; }
    }

    public ProjectDeliverableAttributeSearchListItem DeliverableAttribute
    {
        get { return _deliverableAttribute; }
        protected set { _deliverableAttribute = value; }
    }

    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

        switch (_templateAttribute.DataType)
        {
            case AttributeDataType.Text:
                InitializeTextEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
            case AttributeDataType.Decimal:
                InitializeDecimalEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
            default:
                InitializeUnassignedEditingControl(initialFormattedValue, dataGridViewCellStyle);
                break;
        }
    }

    #region Editing Control Initializers

    private void InitializeUnassignedEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // I hope this isn't needed
        DataGridViewTextBoxEditingControl textEditingControl = this.DataGridView.EditingControl as DataGridViewTextBoxEditingControl;
        if (textEditingControl != null)
        {
            textEditingControl.BorderStyle = BorderStyle.None;
            textEditingControl.Text = (string)this.Value;
        }
    }

    private void InitializeTextEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        TextAttributeSearchListItem textAttribute = (TextAttributeSearchListItem)_templateAttribute;
        TextAttributeEditingControl editingControl = this.DataGridView.EditingControl as TextAttributeEditingControl;
        if (editingControl != null)
        {
            editingControl.BorderStyle = BorderStyle.None;
            editingControl.MaxLength = textAttribute.MaxLength;
            editingControl.Multiline = textAttribute.Multiline;
            editingControl.AcceptsReturn = editingControl.Multiline;

            var value = initialFormattedValue as string;
            editingControl.Text = value == null ? string.Empty : (string)value;
        }
        else
            throw new Exception("There was a problem when attempting to initialize the cell editing control.");
    }

    private void InitializeDecimalEditingControl(object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        DecimalAttributeSearchListItem decimalAttribute = (DecimalAttributeSearchListItem)_templateAttribute;
        DecimalAttributeEditingControl editingControl = this.DataGridView.EditingControl as DecimalAttributeEditingControl;
        if (editingControl != null)
        {
            editingControl.BorderStyle = BorderStyle.None;
            editingControl.MaxLength = 11;
            editingControl.Multiline = false;
            editingControl.AcceptsReturn = false;
            editingControl.TextAlign = HorizontalAlignment.Right;

            var value = initialFormattedValue as string;
            editingControl.Text = value == null ? string.Empty : (string)value;
        }
        else
            throw new Exception("There was a problem when attempting to initialize the cell editing control.");
    }

    #endregion

    protected override object GetFormattedValue(object value,
        int rowIndex, ref DataGridViewCellStyle cellStyle,
        TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter,
        DataGridViewDataErrorContexts context)
    {
        object formattedValue = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
        return formattedValue == null ? string.Empty : (string)formattedValue;
    }
}

This now allows my cell to cleverly detect which data type of the attribute is to be edited and use that when InitializeEditingControl is called. I've only written support so far for the text attribute, which I could have just used a DataGridViewTextBoxEditingControl for, but I needed to understand this in a bit more detail. With a little help from Reflector, I finally got my control to edit and store the value properly:

public class TextAttributeEditingControl: TextBox, IDataGridViewEditingControl
{
    public TextAttributeEditingControl()
    {
        this.TabStop = false;
    }

    #region IDataGridViewEditingControl Members

    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
    {
        this.Font = dataGridViewCellStyle.Font;
        if (dataGridViewCellStyle.BackColor.A < 255)
        {
            // The NumericUpDown control does not support transparent back colors
            Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor);
            this.BackColor = opaqueBackColor;
            this.EditingControlDataGridView.EditingPanel.BackColor = opaqueBackColor;
        }
        else
        {
            this.BackColor = dataGridViewCellStyle.BackColor;
        }
        this.ForeColor = dataGridViewCellStyle.ForeColor;
        this.TextAlign = HorizontalAlignment.Left;
    }

    public DataGridView EditingControlDataGridView { get; set; }

    public object EditingControlFormattedValue
    {
        get { return this.GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting); }
        set { this.Text = (string)value; }
    }

    public int EditingControlRowIndex { get; set; }

    public bool EditingControlValueChanged { get; set; }

    public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
    {
        switch ((keyData & Keys.KeyCode))
        {
            case Keys.Prior:
            case Keys.Next:
                if (!this.EditingControlValueChanged)
                {
                    break;
                }
                return true;

            case Keys.End:
            case Keys.Home:
                if (this.SelectionLength == this.Text.Length)
                {
                    break;
                }
                return true;

            case Keys.Left:
                if (((this.RightToLeft != RightToLeft.No) || ((this.SelectionLength == 0) && (base.SelectionStart == 0))) && ((this.RightToLeft != RightToLeft.Yes) || ((this.SelectionLength == 0) && (base.SelectionStart == this.Text.Length))))
                {
                    break;
                }
                return true;

            case Keys.Up:
                if ((this.Text.IndexOf("\r\n") < 0) || ((base.SelectionStart + this.SelectionLength) < this.Text.IndexOf("\r\n")))
                {
                    break;
                }
                return true;

            case Keys.Right:
                if (((this.RightToLeft != RightToLeft.No) || ((this.SelectionLength == 0) && (base.SelectionStart == this.Text.Length))) && ((this.RightToLeft != RightToLeft.Yes) || ((this.SelectionLength == 0) && (base.SelectionStart == 0))))
                {
                    break;
                }
                return true;

            case Keys.Down:
                {
                    int startIndex = base.SelectionStart + this.SelectionLength;
                    if (this.Text.IndexOf("\r\n", startIndex) == -1)
                    {
                        break;
                    }
                    return true;
                }
            case Keys.Delete:
                if ((this.SelectionLength <= 0) && (base.SelectionStart >= this.Text.Length))
                {
                    break;
                }
                return true;

            case Keys.Return:
                if ((((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == Keys.Shift) && this.Multiline) && base.AcceptsReturn)
                {
                    return true;
                }
                break;
        }
        return !dataGridViewWantsInputKey;
    }

    public Cursor EditingPanelCursor
    {
        get { return Cursors.Default; }
    }

    public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
    {
        return this.Text;
    }

    public void PrepareEditingControlForEdit(bool selectAll)
    {
        if (selectAll)
            this.SelectAll();
        else
            this.SelectionStart = this.Text.Length;
    }

    public bool RepositionEditingControlOnValueChange
    {
        get { return false; }
    }

    #endregion

    private void NotifyDataGridViewOfValueChange()
    {
        this.EditingControlValueChanged = true;
        this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        this.NotifyDataGridViewOfValueChange();
    }
}

Once this was all in place, I tested it with the following code to populate a target DataGridView and see my new column, cell, and editing control in action:

private void PopulateDataGridView(ProjectDeliverableSearchListItem deliverable, DeliverableTemplateSearchListItem template)
{
	// Query lists of attributes used and not yet used
	ProjectDeliverableAttributeSearchList deliverableAttributes = new ProjectDeliverableAttributeSearchList();
	deliverableAttributes.ProjectDeliverableID = deliverable.ID;
	deliverableAttributes.Refresh();

	DeliverableTemplateAttributeSearchList allAttributes = new DeliverableTemplateAttributeSearchList();
	allAttributes.DeliverableTemplateID = template.ID;
	allAttributes.Refresh();

	DeliverableAttributeColumn attributesColumn = new DeliverableAttributeColumn();
	attributesColumn.Name = "Value";

	this.dgvAttributes.Columns.Clear();
	this.dgvAttributes.Columns.Add("Title", "Title");
	this.dgvAttributes.Columns.Add(attributesColumn);

	foreach (var templateAttribute in allAttributes)
	{
		// Find the value that was saved
		var deliverableAttribute = deliverableAttributes.FirstOrDefault(attribute => attribute.DeliverableTemplateAttributeID == templateAttribute.ID);

		// Create the row with the values from the database (if they exist yet)
		int rowIndex = this.dgvAttributes.Rows.Add(templateAttribute.Title, deliverableAttribute != null ? deliverableAttribute.Value : null);
		var row = this.dgvAttributes.Rows[rowIndex];

		// Title cell must be read only
		row.Cells[0].ReadOnly = true;

		// Set the attribute type of the value cell. Cell defaults to "DataGridViewTextBoxEditingControl". See DeliverableAttributeCell.cs
		var deliverableAttributeCell = (DeliverableAttributeCell)row.Cells[1];
		deliverableAttributeCell.SetAttributes(templateAttribute, deliverableAttribute);
	}
}

Since this has some specialized code for my project, I obviously can't go pasting all that stuff too, so I hope you can understand what they do. A "SearchList" is just a query builder that populates itself with multiple values from the database as a special "SearchListItem" type. A deliverable template is a top level template which has an associated designer, and a project deliverable is an instance of a template.


I have some links to similar questions like this, if this doesn't help you:
Since I'm still working on this, I might come up with some problems that I can post here, so add alerts where necessary, and all comments are welcome.
Software Developer, MCP
  • Edited byCodesleuth Monday, October 05, 2009 10:58 AMadded some formatting
  • Marked As Answer byCodesleuth Monday, October 05, 2009 10:59 AM
  •  
Codesleuth  Monday, October 05, 2009 10:56 AM

You can use google to search for other answers

Custom Search

More Threads

• Binding a textbox to DateTime?
• Binding Combobox.SelectedItem to Objects with NULL values
• Database Retreival Using Backgroundworker
• MS Access Forms functionality in VB.Net ??
• Allow multi-line text entry in a datagrid textbox cell, or How to capture ctrl+enter in a datagridview textbox cell
• Displaying a memo field in a Datagridview
• Null DateTime value
• Application Exception?
• SqlDataAdapter wont refresh based on the given stored procedure parameter / Datagrid also
• NullReferenceException after selectedIndexChanged in datagridviewcombobox