简体   繁体   English

DataGridView绑定到包含Dictionary的对象列表

[英]DataGridView bind to a list of Objects which contain a Dictionary

I am successfully binding to a list of objects and setting this as the DataGridViews datasource. 我成功绑定到对象列表并将其设置为DataGridViews数据源。 Definiting columns, at run time, which include the appropriate DataPropertyNames. 在运行时定义列,其中包括相应的DataPropertyNames。

However I now need to add a list to my object class. 但是我现在需要在我的对象类中添加一个列表。 The size of this list is dynamic, but always the same size for all instances of my object. 此列表的大小是动态的,但对于我的对象的所有实例总是大小相同。

So my question is how can I create my DataGridViewTextBoxColumn to create a column for each items within this list? 所以我的问题是如何创建我的DataGridViewTextBoxColumn来为这个列表中的每个项目创建一个列?

Below is my object code, which has been simplified for this question. 下面是我的目标代码,已针对此问题进行了简化。 Within the languages Dictionary will be something like: 在语言中,Dictionary会是这样的:

  • "English", "Hello" “英语”,“你好”
  • "German", "Hallo" “德国人”,“你好”
  • "Spanish", "Hola" “西班牙语”,“Hola”

Ideally the Key would appear as the column name. 理想情况下,密钥将显示为列名称。

Looking like this (each row is a StringItem): 看起来像这样(每行是一个StringItem):

例

public class StringItem
{
    #region Attributes ########################################################################
    string name;    // String name, used to generate the enum for referencing
    string comment; // Helpful description of the string item.
    Dictionary<string, string> languages = new Dictionary<string, string>(); // For language strings.
    #endregion

    #region Public Functions ##################################################################
    public string Name
    {
        get { return name; }
    }

    public string Comment
    {
        get { return comment; }
        set { comment = value; }
    }

    public Dictionary<string, string> Languages
    {
        get { return languages; }
        set { languages = value; }
    }
    #endregion
}

Update: I believe the suggested link in the comments isn't trying to achieve quite the same thing, however it is useful. 更新:我认为评论中建议的链接不是试图实现完全相同的东西,但它很有用。

I can see that by adding the follow code to my StringItem I can directly access the language dictionary doing myObj["English"] 我可以看到,通过在我的StringItem中添加以下代码,我可以直接访问执行myObj["English"]的语言字典

    public string this[string key]
    {
        get
        {
            return languages[key];
        }
        set
        {
            languages[key] = value;
        }
    }

However the DataPropertyName, for each column, doesn't quite work liek this. 但是,对于每一列,DataPropertyName并不是很有效。 I assume it uses reflections? 我认为它使用反射? Can anyone confirm this and tell me if I can implement my own reflection, or whatever DataPropertyName is using, to get my dictionary item. 任何人都可以确认这一点并告诉我是否可以实现我自己的反射,或者DataPropertyName正在使用的任何东西,以获取我的字典项。

This is how I set up the columns: 这是我设置列的方式:

        DataGridViewColumn column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "Name";
        column.Name = "Name";
        dgvStrings.Columns.Add(column);

        foreach (string lang in ProjectSettings.Languages)
        {
            column = new DataGridViewTextBoxColumn();
            column.DataPropertyName = lang; // <<<< THIS ISN'T WORKING.
            column.Name = lang;
            dgvStrings.Columns.Add(column);
        }

You could iterate through your list and add a ColumnHeader for each item. 您可以遍历列表并为每个项目添加ColumnHeader。

Example: 例:

foreach ( var item in list )
{
    someDataGridView.Columns.Add(item + "ColumnHeader", item);
}

Explanation: 说明:
You can add columns programmatically. 您可以通过编程方式添加列。 The first argument being the Column name , item + "ColumnHeader" in this case and the 2nd is Column text eg. 第一个参数是Column name ,在这种情况下为item + "ColumnHeader" ,第二个是Column text例如。 displayed text, in this case item so if it was German that would be the header. 显示的文本,在这种情况下是item ,如果它是German ,那将是标题。

You can create a DataTable containing columns for your class properties and languages, then after editing the data table in DataGridView , revert it back to List<StringItem> . 您可以创建包含类属性和语言列的DataTable ,然后在DataGridView编辑数据表后,将其还原为List<StringItem>

To do so, I suppose you have StringItem . 为此,我想你有StringItem I just refactored your code to make it more clean: 我只是重构了你的代码,使它更干净:

public class StringItem
{
    public static string[] LanguageNames
    {
        get { return new[] { "English", "German", "Spanish" }; }
    }
    public StringItem(string name)
    {
        Name = name;
        Languages = new Dictionary<string, string>();
        LanguageNames.ToList().ForEach(x => Languages.Add(x, null));
    }
    public string Name { get; private set; }
    public string Comment { get; set; }
    public Dictionary<string, string> Languages { get; set; }
}

Then create methods to convert List<StringItem> to a DataTable and vice versa: 然后创建将List<StringItem>转换为DataTable ,反之亦然:

public static class StringItemExtensions
{
    public static DataTable ToDataTable(this List<StringItem> list)
    {
        var dt = new DataTable();
        dt.Columns.Add("Name").ReadOnly = true;
        dt.PrimaryKey = new DataColumn[] { dt.Columns["Name"] };
        dt.Columns.Add("Comment");
        StringItem.LanguageNames.ToList().ForEach(x => dt.Columns.Add(x));
        list.ForEach(item =>
        {
            var values = new List<object>();
            values.Add(item.Name);
            values.Add(item.Comment);
            values.AddRange(item.Languages.Values.Cast<string>());
            dt.Rows.Add(values.ToArray());
        });
        return dt;
    }
    public static List<StringItem> ToStringItemList(this DataTable table)
    {
        return table.AsEnumerable().Select(row =>
        {
            var item = new StringItem(row.Field<string>("Name"));
            foreach (var lang in StringItem.LanguageNames)
                item.Languages[lang] = row.Field<string>(lang);
            return item;
        }).ToList();
    }
}

Now you can edit a List<StringItem> in DataGridView : 现在,您可以在DataGridView编辑List<StringItem>

var list = new List<StringItem>();
list.Add(new StringItem("Key1"));
list.Add(new StringItem("Key2"));
list.Add(new StringItem("Key3"));
this.dataGridView1.DataSource = list.ToDataTable();

After finish editing, it's enough to export the data table to a List<StringItem> : 完成编辑后,将数据表导出到List<StringItem>就足够了:

var list = ((DataTable)this.dataGridView1.DataSource).ToStringItemList();

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM