【问题标题】:How to have custom control in DataGridView display object's value?如何在 DataGridView 显示对象的值中有自定义控件?
【发布时间】:2015-04-01 07:41:08
【问题描述】:

我有一个位于here 的示例项目。

该项目有一个主窗体Form1,用户可以在其中在datagridview 中输入客户。 CustomerType 列是一个自定义控件,当用户点击按钮时,会弹出一个搜索表单Form2

搜索表单中填充了CustomerType 类型的列表。用户可以通过双击该行来选择一条记录,该对象应在自定义控件中设置。然后DataGridView 应该显示Description 属性,但在后台每个单元格都应该保存该值(即CustomerType 实例)。

相关代码位于以下类中:

列类:

public class DataGridViewCustomerTypeColumn : DataGridViewColumn
{
    public DataGridViewCustomerTypeColumn()
        : base(new CustomerTypeCell())
    { }

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

            base.CellTemplate = value;
        }
    }
}

细胞类:

public class CustomerTypeCell : DataGridViewTextBoxCell
{
    public CustomerTypeCell()
        : base()
    { }

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

        CustomerTypeSearch ctl = DataGridView.EditingControl as CustomerTypeSearch;

        if (this.Value == null)
            ctl.Value = (CustomerType)this.DefaultNewRowValue;
        else
            ctl.Value = (CustomerType)this.Value;
    }

    public override Type EditType
    {
        get { return typeof(CustomerTypeSearch); }
    }

    public override Type ValueType
    {
        get { return typeof(CustomerType); }
    }

    public override object DefaultNewRowValue
    {
        get { return null; }
    }
}

还有自定义控件:

public partial class CustomerTypeSearch : UserControl, IDataGridViewEditingControl
{
    private DataGridView dataGridView;
    private int rowIndex;
    private bool valueChanged = false;
    private CustomerType value;

    public CustomerTypeSearch()
    {
        InitializeComponent();
    }

    public CustomerType Value
    {
        get { return this.value; }
        set 
        { 
            this.value = value;

            if (value != null)
                textBoxSearch.Text = value.Description;
            else
                textBoxSearch.Clear();
        }
    }

    private void buttonSearch_Click(object sender, EventArgs e)
    {
        Form2 f = new Form2();

        DialogResult dr = f.ShowDialog(this);

        if (dr == DialogResult.OK)
        {
            Value = f.SelectedValue;
        }
    }

    #region IDataGridViewEditingControl implementation

    public object EditingControlFormattedValue
    {
        get 
        {
            if (this.value != null)
                return this.value.Description;
            else
                return null;
        }
        set 
        { 
            if (this.value != null)
                this.value.Description = (string)value; 
        }
    }

    public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
    {
        return EditingControlFormattedValue;
    }

    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
    {
        this.BorderStyle = BorderStyle.None;
        this.Font = dataGridViewCellStyle.Font;
    }

    public int EditingControlRowIndex
    {
        get { return rowIndex; }
        set { rowIndex = value; }
    }

    public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
    {
        return false;
    }

    public void PrepareEditingControlForEdit(bool selectAll)
    {
        //No preparation needs to be done 
    }

    public bool RepositionEditingControlOnValueChange
    {
        get { return false; }
    }

    public DataGridView EditingControlDataGridView
    {
        get { return dataGridView; }
        set { dataGridView = value; }
    }

    public bool EditingControlValueChanged
    {
        get { return valueChanged; }
        set { valueChanged = value; }
    }

    public Cursor EditingPanelCursor
    {
        get { return base.Cursor; }
    }

    #endregion

    private void CustomerTypeSearch_Resize(object sender, EventArgs e)
    {
        buttonSearch.Left = this.Width - buttonSearch.Width;
        textBoxSearch.Width = buttonSearch.Left;
    }
}

但是,DataGridView 没有显示文本,也没有为每个单元格保留 CustomerType 值。

我错过了什么?

【问题讨论】:

  • 请把相关代码贴在这里。
  • 覆盖CustomerType 类中的ToString() 方法。 DataGirdView 使用ToString() 方法仅显示字符串。
  • 我做到了,它有效。但是 PatseFormattedValue 想在我的对象中转换显示的字符串

标签: c# visual-studio datagridview


【解决方案1】:

首先,将ToString() 方法覆盖到您的CustomerType 类中。

其次,为避免解析错误,在CustomerTypeSearch类中修改如下方法:

public CustomerType Value
{
    get { return this.value; }
    set
    {
        this.value = value;

        if (value != null)
            textBoxSearch.Text = value.Description;
        else
            textBoxSearch.Clear();

        valueChanged = true;
        if ((EditingControlDataGridView.CurrentCell as CustomerTypeCell) != null)
            (EditingControlDataGridView.CurrentCell as CustomerTypeCell).Value = value;
    }
}

然后,将此函数添加到CustormerTypeCell 类中:

protected override bool SetValue(int rowIndex, object value)
{
    if (value != null)
        return base.SetValue(rowIndex, value);
    return false;
}

最后,添加这个来处理数据错误:

private void dataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
    e.Cancel = false;
}

【讨论】:

  • 我刚刚收到消息:“DataGridView 中发生异常”。不知何故,值始终为空。
  • 我无法重现您的异常。 ParseFormattedValue 函数什么时候调用?
  • 当焦点离开单元格时(例如按 Tab)。
  • 还是不行。但是,我注意到如果在 valueChanged = true; 下方添加这行:this.EditingControlDataGridView.NotifyCurrentCellDirty(true);,它将引发 ParseFormattedValue 事件。
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 2012-05-10
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2021-08-11
相关资源
最近更新 更多