c# - 如何在 DataGridView 显示对象的值中自定义控件?

标签 c# visual-studio datagridview

我有一个示例项目位于 here .

该项目有一个主窗体 Form1,用户可以在其中在数据 GridView 中输入客户。 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 值。

我错过了什么?

最佳答案

首先,将 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;
}

关于c# - 如何在 DataGridView 显示对象的值中自定义控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29385362/

相关文章:

c# - 在 ASP.NET 中, 'ASP' 代码叫什么?

visual-studio - 如果我是个人开发者,我应该打扰 VS Team System 吗?

c# - LINQ 查询未检索保存的数据

c# - 数据关系插入和外键

vb.net - 如何防止按 Enter 键结束 DataGridView 中的 EditMode?

c# - 创建 CURL 请求 ASP.NET

c# - 在 Compact Framework 3.5 中使用 lambda 表达式加载类在首次加载时速度很慢

c# - 为什么 SQL Server Compact 中的日期时间类型会对值进行舍入?

c# - UWP - 按下指针不起作用

c# - VS2010拒绝编译命名空间,说它不存在