简体   繁体   English

使用ComboBox在DataGridView中显示二级属性

[英]Using ComboBox to show second-level properties in DataGridView

As I understand it, ComboBox columns are more dynamic for binding in DataGridView than standard columns, and this flexibility can be used to use DisplayMembers from second-order properties.据我了解,ComboBox 列在 DataGridView 中的绑定比标准列更具动态性,并且这种灵活性可用于使用二阶属性中的 DisplayMembers。 This approach is the first mentioned here by Mr. Aghaei .这种方法是Aghaei先生在这里首次提到的。

However, I'm not getting it right.但是,我没有做对。 My application still throws the exception that "Name" doesn't exist.我的应用程序仍然抛出“名称”不存在的异常。

 public void CreateEmployeeTable()
        {

            DataGridViewComboBoxColumn jobTitleColumn = new DataGridViewComboBoxColumn();
            jobTitleColumn.HeaderText = "Job Title";
            jobTitleColumn.DataPropertyName = "JobTitle";
            jobTitleColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
            jobTitleColumn.DataPropertyName = "ID";
            jobTitleColumn.DataSource = globalEmployeeList;
            jobTitleColumn.ValueMember = "ID";
            jobTitleColumn.DisplayMember = "Name";
            jobTitleColumn.ReadOnly = true;

            employeeGridView.AutoGenerateColumns = false;
            employeeGridView.ColumnCount = 2;
            employeeGridView.Columns[0].HeaderText = "Employee ID";
            employeeGridView.Columns[0].DisplayIndex = 0;
            employeeGridView.Columns[0].DataPropertyName = "ID";
            employeeGridView.Columns[1].HeaderText = "Name";
            employeeGridView.Columns[1].DataPropertyName = "ListView";
            employeeGridView.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            employeeGridView.Columns.Add(jobTitleColumn);
            
            employeeGridView.DataSource = globalEmployeeList;                                                                               
        }

Here is the class definition:这是 class 定义:

     
    public class EmployeeModel
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Nickname { get; set; }
        public DepartmentModel Department { get; set; }
        public TitleModel JobTitle { get; set; }
        public DateTime HireDate { get; set; }
        public List<EmailModel> EmailList { get; set; } = new List<EmailModel>();
        public List<PhoneModel> PhoneList { get; set; } = new List<PhoneModel>();
        public List<RestrictionModel> RestrictionsList { get; set; } = new List<RestrictionModel>();
        public List<CitationModel> CitationsList { get; set; } = new List<CitationModel>();
        public List<CertificationModel> CertificationList { get; set; } = new List<CertificationModel>();

        public string ListView
        {
            get
            {
                return $"{LastName}, {FirstName}";
            }
        }

        public string ToEmailString()
        {
            IEnumerable<string> employeeEmailStrings = EmailList.Select(emmod => emmod.ToString());
            string employeeEmailString = string.Join($"{Environment.NewLine}", employeeEmailStrings);

            IEnumerable<string> certificationStrings = CertificationList.Select(clistmod => clistmod.ToString());
            string certificationString = string.Join($"{Environment.NewLine}", certificationStrings);

            IEnumerable<string> phoneStrings = PhoneList.Select(plistmod => plistmod.ToString());
            string phoneString = string.Join($"{Environment.NewLine}", phoneStrings);

            return $"{FirstName}, {LastName}: {Environment.NewLine} -{JobTitle.Name}- {Environment.NewLine} {employeeEmailString} {Environment.NewLine} {certificationString} {Environment.NewLine} {phoneString}";
        }



        public class EmailModel
        {
            public int ID { get; set; }
            public string Address { get; set; }
            public string Type { get; set; }

            public override string ToString()
            {
                return $"{Address} ({Type})";
            }
        }

        public class PhoneModel
        {
            public int ID { get; set; }
            public string Number { get; set; }
            public string Type { get; set; }
            public override string ToString()
            {
                return $"{Number} ({Type})";
            }

        }
    }

And the definition for TitleModel: TitleModel 的定义:

    public class TitleModel
    {
        public string Name { get; set; }
        public int ID { get; set; }  

    }
}

To support the post Show Properties of a Navigation Property in DataGridView (Second Level Properties) I've already shared a few example in the same post or this one which allows showing second level properties and allow editing them.为了支持在 DataGridView 中显示导航属性的属性(二级属性) ,我已经在同一篇文章或这个允许显示二级属性并允许编辑它们的示例中共享了一些示例。

Here I will share a few more examples, each example has been written as a minimal complete verifiable example, you can just copy and paste in an empty form and they will work.在这里我将分享更多示例,每个示例都被编写为一个最小的完整可验证示例,您只需复制并粘贴到一个空表单中,它们就可以工作。

These are the examples:这些是示例:

  • Using ToString()使用 ToString()
  • Using CellFormatting使用单元格格式化
  • Using ComboBox Column for Navigation Object使用 ComboBox 列进行导航 Object
  • Using ComboBox Column for Foreign key column使用 ComboBox 列作为外键列

Example - Using ToString()示例 - 使用 ToString()

When: You don't want to change JobTitle of Employee何时:您不想更改 Employee 的JobTitle

How: By overriding ToString method of JobTitle如何:通过覆盖JobTitleToString方法

class JobTitle
{
    public int Id { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name;
    }
}
class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public JobTitle JobTitle { get; set; }
}
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    var jobTitles = new List<JobTitle>() {
        new JobTitle {Id= 1, Name="Manager" },
        new JobTitle {Id= 2, Name="Employee" },
    };
    var employees = new List<Employee>() {
        new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
        new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
        new Employee{ Id = 3, Name ="Jack", JobTitle = jobTitles[1] },
    };
    var dg = new DataGridView();
    dg.Dock = DockStyle.Fill;
    dg.DataSource = employees;
    this.Controls.Add(dg);
}

Example - Using CellFormatting示例 - 使用 CellFormatting

When: You don't want to change JobTitle of Employee何时:您不想更改 Employee 的JobTitle

How: By handling CellFormatting event of DataGridView and setting Value of the event args to a string representation of JobTitle如何:通过处理DataGridViewCellFormatting事件并将事件 args 的Value设置为JobTitle的字符串表示形式

class JobTitle
{
    public int Id { get; set; }
    public string Name { get; set; }
}
class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public JobTitle JobTitle { get; set; }
}
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    var jobTitles = new List<JobTitle>() {
        new JobTitle {Id= 1, Name="Manager" },
        new JobTitle {Id= 2, Name="Employee" },
    };
    var employees = new List<Employee>() {
        new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
        new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
        new Employee{ Id = 3, Name ="Jack", JobTitle = jobTitles[1] },
    };
    var dg = new DataGridView();
    dg.Dock = DockStyle.Fill;
    dg.DataSource = employees;
    dg.CellFormatting += (obj, args) =>
    {
        if (args.RowIndex >= 0 &&
            dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
            args.Value = ((Employee)dg.Rows[args.RowIndex].DataBoundItem).JobTitle.Name;
    };
    this.Controls.Add(dg);
}

Example - Using ComboBox Column for Foreign key column示例 - 使用 ComboBox 列作为外键列

When: You want to be able to change the JobTitle of Employee and you have the foreign key column in your model.何时:您希望能够更改EmployeeJobTitle并且您的 model 中有外键列。

How: Using a DataGridViewComboBoxColumn for that property, having a data source containing all job titles, and setting DisplayMember and ValueMember to proper properties.方法对该属性使用DataGridViewComboBoxColumn ,拥有一个包含所有职位的数据源,并将DisplayMemberValueMember设置为适当的属性。

class JobTitle
{
    public int Id { get; set; }
    public string Name { get; set; }
}
class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int JobTitleId { get; set; }
}
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    var jobTitles = new List<JobTitle>() {
        new JobTitle {Id= 1, Name="Manager" },
        new JobTitle {Id= 2, Name="Employee" },
    };
    var employees = new List<Employee>() {
        new Employee{ Id = 1, Name ="John", JobTitleId = 1 },
        new Employee{ Id = 2, Name ="Jane", JobTitleId = 2 },
        new Employee{ Id = 2, Name ="Jack", JobTitleId = 2 },
    };
    var dg = new DataGridView();
    dg.Dock = DockStyle.Fill;
    dg.DataSource = employees;
    dg.Columns.Add(new DataGridViewTextBoxColumn() 
    { 
        DataPropertyName = "Id", HeaderText = "Id" 
    });
    dg.Columns.Add(new DataGridViewTextBoxColumn() 
    {
        DataPropertyName = "Name", HeaderText = "Name" 
    });
    dg.Columns.Add(new DataGridViewComboBoxColumn()
    {
        DataPropertyName = "JobTitleId",
        HeaderText = "JobTitleId",
        DataSource = jobTitles,
        ValueMember = "Id",
        DisplayMember = "Name",
    });
    this.Controls.Add(dg);
}

Example - Using ComboBox Column for Navigation Object示例 - 使用 ComboBox 列进行导航 Object

When: You want to be able to change the JobTitle of Employee and you don't have the foreign key column in your model, instead you want to use the navigation object in your model.何时:您希望能够更改EmployeeJobTitle并且您的 model 中没有外键列,而是希望在 Z20F35E630DAF44DBFA4C3F68F5399D8C8 中使用导航 object。

How: Using a DataGridViewComboBoxColumn for that property, having a data source containing all job titles, without setting DisplayMember and ValueMember to proper properties.方法对该属性使用DataGridViewComboBoxColumn ,具有包含所有职位的数据源,无需将DisplayMemberValueMember设置为适当的属性。 Then handling CellFormatting to set the display value of the cell and handling CellParsing to get value from ComboBox and put into the cell.然后处理CellFormatting设置单元格的显示值,处理CellParsingComboBox获取值并放入单元格。

class JobTitle
{
    public int Id { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name;
    }
}
class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public JobTitle JobTitle { get; set; }
}

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    var jobTitles = new List<JobTitle>() {
        new JobTitle {Id= 1, Name="Manager" },
        new JobTitle {Id= 1, Name="Employee" },
    };
    var employees = new List<Employee>() {
        new Employee{ Id = 1, Name ="John", JobTitle = jobTitles[0] },
        new Employee{ Id = 2, Name ="Jane", JobTitle = jobTitles[1] },
        new Employee{ Id = 2, Name ="Jack", JobTitle = jobTitles[1] },
    };
    var dg = new DataGridView();
    dg.Dock = DockStyle.Fill;
    dg.DataSource = employees;
    dg.Columns.Add(new DataGridViewTextBoxColumn() 
    { 
        DataPropertyName = "Id", HeaderText = "Id" 
    });
    dg.Columns.Add(new DataGridViewTextBoxColumn() 
    {
        DataPropertyName = "Name", HeaderText = "Name" 
    });
    dg.Columns.Add(new DataGridViewComboBoxColumn()
    {
        DataPropertyName = "JobTitle",
        HeaderText = "JobTitle",
        DataSource = jobTitles,
    });
    dg.CellFormatting += (obj, args) =>
    {
        if (args.RowIndex >= 0 &&
            dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
        {
            args.Value = 
        ((Employee)dg.Rows[args.RowIndex].DataBoundItem).JobTitle.ToString();
        }
    };
    dg.CellParsing += (obj, args) =>
    {
        if (args.RowIndex >= 0 &&
            dg.Columns[args.ColumnIndex].DataPropertyName == "JobTitle")
        {
            args.Value = ((ComboBox)dg.EditingControl).SelectedItem;
            args.ParsingApplied = true;
        }
    };
    this.Controls.Add(dg);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 DataGridView 中显示导航属性的属性(二级属性) - Show Properties of a Navigation Property in DataGridView (Second Level Properties) 如何将DataGrid列组合框绑定到第二级列表 - How to bind a datagrid column combobox to a second-level list 如何使用BindingSource绑定DataGridView中的导航属性(二级属性)? - How to bind a Navigation Property (second level properties) in DataGridView using BindingSource? 在二级缓存中缓存NHibernate DetachedCriteria - Caching NHibernate DetachedCriteria in second-level cache 创建二级AppDomain挂起 - Creating second-level AppDomain hangs 使用Redis的NHibernate二级缓存与仅使用Redis - NHibernate second-level cache using Redis vs just using Redis 如何使用BindingSource在DataGridView的单列中绑定Navigation Property(二级模型的两个属性)? - How to bind Navigation Property (second level model's two properties) in DataGridView's single column using BindingSource? 如何将DataGrid绑定到数据源的第二级属性? - How to bind DataGrid to a second-level property of a data source? wpf Datagrid DataGridTemplateColumn TextBlock中的二级属性绑定 - Second-level property binding in wpf Datagrid DataGridTemplateColumn TextBlock 组合框项目未显示在datagridview中 - combobox items not show in datagridview
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM