C# 将类中包含的字典绑定到DataGrid

C# 将类中包含的字典绑定到DataGrid,c#,data-binding,datagrid,C#,Data Binding,Datagrid,我有以下数据结构的列表,我想在datagrid中显示这些数据结构: public class receiver { public string Name { get; set; } public string Mail { get; set; } public Dictionary<string, string> ReplacementText { get; set; } } public void Init() { List<receiver> rec

我有以下数据结构的列表,我想在datagrid中显示这些数据结构:

public class receiver
{
  public string Name { get; set; }
  public string Mail { get; set; }
  public Dictionary<string, string> ReplacementText { get; set; }
}

public void Init()
{
  List<receiver> receivers = new List<receiver>();
  // add some instances of receivers

  MyDataGrid.DataContext = receivers;
}
用户应该能够编辑所有数据。显然,我不能像上面的例子那样简单地绑定列表。此外,ReplacementText字典中的条目是动态的(即,用户可以添加更多的键,这些键也应该在datagrid中可见)。有没有想过,我怎么会做出这样的行为

提前感谢,
弗兰克

我的建议

  • 字典
    转换为
    数据表

    DataTable dt=ConvertTo(接收方[i].ReplacementText)

  • 将控件绑定到已转换的
    DataTable

  • 下面是将字典转换为数据表的代码

        ///
        ///Converts a Dictionary of the given type to a DataTable
        ///     
        public static DataTable ConvertTo<T>(Dictionary<string, T> list, string dataTableName)
        {
            DataTable table = CreateTable1<T>(dataTableName);
            Type entityType = typeof(T);
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);
    
            foreach (KeyValuePair<string, T> item in list)
            {
                DataRow row = table.NewRow();
    
                foreach (PropertyDescriptor prop in properties)
                {
                    if (prop.PropertyType.FullName == "System.String")
                    {
                        if (prop.GetValue(item.Value) == null)
                        {
                            row[prop.Name] = prop.GetValue(item.Value);
                        }
                        else
                        {
                            row[prop.Name] = prop.GetValue(item.Value).ToString().Replace("'", "''");
                        }
                    }
                    else
                    {
                        row[prop.Name] = prop.GetValue(item.Value);
                    }
                }
                table.Rows.Add(row);
            }
            return table;
        }
        ///
        /// Create a DataTable wich columns based on the properties of the given type <T>
        ///
        public static DataTable CreateTable<T>(string dataTableName)
        {
            Type entityType = typeof(T);
            DataTable table = new DataTable(dataTableName);
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);
    
            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, prop.PropertyType);
            }
            return table;
        }
    
    ///
    ///将给定类型的字典转换为数据表
    ///     
    公共静态DataTable ConvertTo(字典列表、字符串dataTableName)
    {
    DataTable=CreateTable1(dataTableName);
    类型entityType=类型(T);
    PropertyDescriptorCollection属性=TypeDescriptor.GetProperties(entityType);
    foreach(列表中的KeyValuePair项)
    {
    DataRow行=table.NewRow();
    foreach(属性中的PropertyDescriptor属性)
    {
    if(prop.PropertyType.FullName==“System.String”)
    {
    if(prop.GetValue(item.Value)==null)
    {
    行[prop.Name]=prop.GetValue(item.Value);
    }
    其他的
    {
    行[prop.Name]=prop.GetValue(item.Value).ToString().Replace(“,”);
    }
    }
    其他的
    {
    行[prop.Name]=prop.GetValue(item.Value);
    }
    }
    table.Rows.Add(行);
    }
    返回表;
    }
    ///
    ///基于给定类型的属性创建包含列的DataTable
    ///
    公共静态DataTable CreateTable(字符串dataTableName)
    {
    类型entityType=类型(T);
    DataTable=新的DataTable(dataTableName);
    PropertyDescriptorCollection属性=TypeDescriptor.GetProperties(entityType);
    foreach(属性中的PropertyDescriptor属性)
    {
    table.Columns.Add(prop.Name,prop.PropertyType);
    }
    返回表;
    }
    
    不能在双向模式下绑定dictionary对象,因为它的
    键和
    值属性是只读的。但是,您可以使用此代码替换字典部分

     public class KeyValueRow<K,V>:INotifyPropertyChanged
        {
            public  KeyValueRow(K key,V value)
            {
                this.Key = key;
                this.Value = value; 
            }
            private K _key;
            private V _value;  
                 
            public K Key
            {
                get { return _key;  }
                set
                {
                    if (!EqualityComparer<K>.Default.Equals(_key, value)) 
                    {
                        _key = value;  
                        RaisePropertyChanged("Key");
                    }
                }
            }
    
            private void RaisePropertyChanged(string p)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));  
            }
            public V Value
            {
                get { return _value; }
                set
                {
                    if (!EqualityComparer<V>.Default.Equals(_value, value))
                    {
                       _value = value;
                       RaisePropertyChanged("Value");
                    }
                }
            }              
            //prefarble way  as it evit to check the for null when raising  event 
            public event PropertyChangedEventHandler PropertyChanged = delegate{};
    
        }
    
    公共类KeyValueRow:INotifyPropertyChanged
    {
    公钥值行(K键,V值)
    {
    这个。键=键;
    这个。值=值;
    }
    私钥;
    私人V_值;
    公钥
    {
    获取{return\u key;}
    设置
    {
    如果(!EqualityComparer.Default.Equals(_键,值))
    {
    _键=值;
    RaisePropertyChanged(“密钥”);
    }
    }
    }
    私有void raiseProperty已更改(字符串p)
    {
    房地产变更(这是新的房地产变更发展(p));
    }
    公共价值
    {
    获取{返回_值;}
    设置
    {
    如果(!EqualityComparer.Default.Equals(_值,值))
    {
    _价值=价值;
    提升财产变更(“价值”);
    }
    }
    }              
    //在引发事件时检查空值时,使用prefarble方法
    公共事件PropertyChangedEventHandler PropertyChanged=委托{};
    }
    
    你可以用它来代替字典

     public ObservableCollection<KeyValueRow<string, string>> ReplacementText { get; set; }
    
    public observeCollection ReplacementText{get;set;}
    
    最后应用主细节场景,如示例所示


    希望这些帮助

    谢谢你的提示,朱莉!我不需要更改dict中的条目,我只需要更改dict中irems值的内容。我确实更改了一些类,因此我能够绑定ReplacementText[0]。不幸的是,ReplacementText[“Name”]不起作用,因为您不能在绑定中使用感叹号。谢谢您的提示,但是这些值将在列中,但我需要在行中使用它们。我试了一下,把dict改成了,这样我就可以用ReplacementText[I]代替bin了
     public class KeyValueRow<K,V>:INotifyPropertyChanged
        {
            public  KeyValueRow(K key,V value)
            {
                this.Key = key;
                this.Value = value; 
            }
            private K _key;
            private V _value;  
                 
            public K Key
            {
                get { return _key;  }
                set
                {
                    if (!EqualityComparer<K>.Default.Equals(_key, value)) 
                    {
                        _key = value;  
                        RaisePropertyChanged("Key");
                    }
                }
            }
    
            private void RaisePropertyChanged(string p)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));  
            }
            public V Value
            {
                get { return _value; }
                set
                {
                    if (!EqualityComparer<V>.Default.Equals(_value, value))
                    {
                       _value = value;
                       RaisePropertyChanged("Value");
                    }
                }
            }              
            //prefarble way  as it evit to check the for null when raising  event 
            public event PropertyChangedEventHandler PropertyChanged = delegate{};
    
        }
    
     public ObservableCollection<KeyValueRow<string, string>> ReplacementText { get; set; }