如何将两个可编辑和可编辑的 DataGridView 绑定到列表和子列表?
How can I have two editable and updatable DataGridViews bounded to a list and sub-list?
我有一个名为 listInput
的 List<Input>
,其中包含名为 friends
的 List<class>
类型的 属性:
List<Input> listInput=new List<Input>();
BindingList<Input> blInput;
BindingSource bsInput;
public class Input
{
public string Name { get; set; }
public List<Friend> friends{ get; set; }
}
public class Friend
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
我有两个 DataGridView
控件,分别命名为 dgInput
和 dgFriends
。
dgInput
像这样绑定到 BindingList
:
blInput = new BindingList<Input>(listInput);
bsInput = new BindingSource(blInput, null);
dgInput.DataSource = bsInput;
dgInput
是 可编辑 和 可更新 在 运行 时间在用户更改 [=] 上的任何单元格后17=]。
问题是:如何将 dgFriends
绑定到子列表 friends
,以便在 dgInput
当前行更改时自动更新?
当用户更改 dgFriends
上的任何单元格时,可以更新 dgFriens
也很重要(listInput
的属性必须保留更改)。
这是一个简单的例子:
第一个 DataGridView 使用您定义的 BindingSource。此 BindingSource 的 DataSource 设置为 List<Input>
集合。此 DGV 只能显示 List<Input>
中的 Name
属性,因为您无法显示包含单个值和值集合的行。
BindingSource 的 DataMember
必须为空(或 null):如果将 Name
设置为 DataMember
,结果将得到一个 Char
的数组,而不是一个细绳。
创建了第二个 BindingSource:其 DataSource 设置为现有的 BindingSource。在这种情况下,DataMember
被显式设置为 Friends
属性,它表示 List<class>
个对象(单个对象表示将向第二个 DGV 的行)。
这会在两个 BindingSource 对象之间生成一个活动绑定(关系):当第一个 BindingSource.Current
对象更改时,第二个 BindingSource 将随之更改,显示其 Current
对象(List<Friend>
链接到当前 Name
属性)。
这两个 class 的所有属性都是可编辑的。
注:
我已经在 Input
class 中实现了 INotifyPropertyChanged 接口来通知 Name
属性 的变化:它不是严格要求的(或者,它不是必需的)完全没有)在这种情况下,但你可能想把它放在那里,你以后很可能会需要它。
List<Input> listInput = new List<Input>();
BindingSource bsInput = null;
public SomeForm()
{
InitializeComponent();
bsInput = new BindingSource(listInput, "");
var bsFriends = new BindingSource(bsInput, "Friends");
dataGridView1.DataSource = bsInput;
dataGridView2.DataSource = bsFriends;
}
public class Input : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string m_Name = string.Empty;
public string Name {
get => m_Name;
set { m_Name = value;
NotifyPropertyChanged(nameof(this.Name));
}
}
public List<Friend> Friends { get; set; } = new List<Friend>();
private void NotifyPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Friend {
public string FirstName { get; set; }
public string LastName { get; set; }
}
这是它的工作原理:
示例对象初始化,用于测试:
listInput.AddRange(new[] {
new Input() {
Name = "Name One", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of One"},
new Friend () { FirstName = "Second", LastName = "Friend of One"},
new Friend () { FirstName = "Third", LastName = "Friend of One"},
}
},
new Input() {
Name = "Name Two", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of Two"},
new Friend () { FirstName = "Second", LastName = "Friend of Two"},
new Friend () { FirstName = "Third", LastName = "Friend of Two"},
}
},
new Input() {
Name = "Name Three", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of Three"},
new Friend () { FirstName = "Second", LastName = "Friend of Three"},
new Friend () { FirstName = "Third", LastName = "Friend of Three"},
}
}
});
我有一个名为 listInput
的 List<Input>
,其中包含名为 friends
的 List<class>
类型的 属性:
List<Input> listInput=new List<Input>();
BindingList<Input> blInput;
BindingSource bsInput;
public class Input
{
public string Name { get; set; }
public List<Friend> friends{ get; set; }
}
public class Friend
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
我有两个 DataGridView
控件,分别命名为 dgInput
和 dgFriends
。
dgInput
像这样绑定到 BindingList
:
blInput = new BindingList<Input>(listInput);
bsInput = new BindingSource(blInput, null);
dgInput.DataSource = bsInput;
dgInput
是 可编辑 和 可更新 在 运行 时间在用户更改 [=] 上的任何单元格后17=]。
问题是:如何将 dgFriends
绑定到子列表 friends
,以便在 dgInput
当前行更改时自动更新?
当用户更改 dgFriends
上的任何单元格时,可以更新 dgFriens
也很重要(listInput
的属性必须保留更改)。
这是一个简单的例子:
第一个 DataGridView 使用您定义的 BindingSource。此 BindingSource 的 DataSource 设置为
List<Input>
集合。此 DGV 只能显示List<Input>
中的Name
属性,因为您无法显示包含单个值和值集合的行。
BindingSource 的DataMember
必须为空(或 null):如果将Name
设置为DataMember
,结果将得到一个Char
的数组,而不是一个细绳。创建了第二个 BindingSource:其 DataSource 设置为现有的 BindingSource。在这种情况下,
DataMember
被显式设置为Friends
属性,它表示List<class>
个对象(单个对象表示将向第二个 DGV 的行)。
这会在两个 BindingSource 对象之间生成一个活动绑定(关系):当第一个 BindingSource.Current
对象更改时,第二个 BindingSource 将随之更改,显示其 Current
对象(List<Friend>
链接到当前 Name
属性)。
这两个 class 的所有属性都是可编辑的。
注:
我已经在 Input
class 中实现了 INotifyPropertyChanged 接口来通知 Name
属性 的变化:它不是严格要求的(或者,它不是必需的)完全没有)在这种情况下,但你可能想把它放在那里,你以后很可能会需要它。
List<Input> listInput = new List<Input>();
BindingSource bsInput = null;
public SomeForm()
{
InitializeComponent();
bsInput = new BindingSource(listInput, "");
var bsFriends = new BindingSource(bsInput, "Friends");
dataGridView1.DataSource = bsInput;
dataGridView2.DataSource = bsFriends;
}
public class Input : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string m_Name = string.Empty;
public string Name {
get => m_Name;
set { m_Name = value;
NotifyPropertyChanged(nameof(this.Name));
}
}
public List<Friend> Friends { get; set; } = new List<Friend>();
private void NotifyPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Friend {
public string FirstName { get; set; }
public string LastName { get; set; }
}
这是它的工作原理:
示例对象初始化,用于测试:
listInput.AddRange(new[] {
new Input() {
Name = "Name One", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of One"},
new Friend () { FirstName = "Second", LastName = "Friend of One"},
new Friend () { FirstName = "Third", LastName = "Friend of One"},
}
},
new Input() {
Name = "Name Two", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of Two"},
new Friend () { FirstName = "Second", LastName = "Friend of Two"},
new Friend () { FirstName = "Third", LastName = "Friend of Two"},
}
},
new Input() {
Name = "Name Three", Friends = new List<Friend>() {
new Friend () { FirstName = "First", LastName = "Friend of Three"},
new Friend () { FirstName = "Second", LastName = "Friend of Three"},
new Friend () { FirstName = "Third", LastName = "Friend of Three"},
}
}
});