如何将两个可编辑和可更新的DataGridView绑定到一个列表和子列表? [英] How can I have two editable and updatable DataGridViews bounded to a list and sub-list?
问题描述
我有一个名为 listInput
的 List< Input>
,其中包含类型为 List< class>
的属性,名称为 friends 代码>:
List< Input>listInput =新列表< Input>();BindingList< Input>blInput;BindingSource bsInput;公共类输入{公共字符串名称{get;放;}公开列表<朋友>朋友{得到;放;}}公开课的朋友{公共字符串FirstName {get;放;}公共字符串LastName {get;放;}}
我有两个 DataGridView
控件,分别名为 dgInput
和 dgFriends
. dgInput
这样绑定到 BindingList
:
blInput = new BindingList< Input>(listInput);bsInput =新的BindingSource(blInput,null);dgInput.DataSource = bsInput;
用户更改 dgInput
上的任何单元格后,
dgInput
可以在运行时可编辑和可更新.
问题是:如何将 dgFriends
绑定到子列表 friends
,以便在 dgInput
curretn Row更改时它会自动更新?
同样重要的是,当用户更改 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对象之间生成活动绑定(关系):当第一个
样本对象初始化,用于测试:
listInput.AddRange(new [] {新的Input(){名字=名字一",朋友=新列表<朋友>(){new Friend(){FirstName ="First",LastName =一个人的朋友"},new Friend(){FirstName ="Second",LastName =一个人的朋友"},new Friend(){FirstName ="Third",LastName =一个人的朋友"},}},新的Input(){名称=名称二",朋友=新列表<朋友>(){new Friend(){FirstName ="First",LastName ="Two of Friends"},new Friend(){FirstName ="Second",LastName ="Two of Friends"},new Friend(){FirstName ="Third",LastName ="Two of Friends"},}},新的Input(){名称=名称三",朋友=新列表<朋友>(){new Friend(){FirstName ="First",LastName =三个朋友"},new Friend(){FirstName ="Second",LastName =三个朋友"},new Friend(){FirstName ="Third",LastName =三个朋友"},}}});
I have a List<Input>
named listInput
that contains property of type a List<class>
named friends
:
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; }
}
I have two DataGridView
controls, named dgInput
and dgFriends
.
dgInput
is bound to a BindingList
like this:
blInput = new BindingList<Input>(listInput);
bsInput = new BindingSource(blInput, null);
dgInput.DataSource = bsInput;
dgInput
is editable and updatable at run-time after user changes any cell on dgInput
.
The question is: how can I bind dgFriends
to sublist friends
, so that it will automatically update when the dgInput
curretn Row changes?
It's also important that dgFriens
can be updated when an User changes any cell on dgFriends
(the properties of listInput
must preserve the changes).
Here's a simple example:
The first DataGridView uses the BindingSource you defined. The DataSource of this BindingSource is set to the
List<Input>
collection. This DGV can only show theName
property from theList<Input>
, since you cannot present Rows containing both single values and collections of values.
TheDataMember
of the BindingSource must be empty (or null): if you setName
asDataMember
, you'll get an array ofChar
as a result instead of a string.A second BindingSource is created: its DataSource is set to the existing BindingSource. In this case, the
DataMember
is set explicitly to theFriends
property, which represents aList<class>
objects (a single object that represents a collection that will provide the data to the Rows of the second DGV).
This generates an active binding (a relationship) between the two BindingSource objects: when the first BindingSource.Current
object changes, the second BindingSource will follow, showing its Current
object (the List<Friend>
linked to the current Name
property).
All properties of the two classes are editable.
Note:
I've implemented the INotifyPropertyChanged interface in the Input
class to notify changes of the Name
property: it's not strictly required (or, it' not required at all) in this context, but you may want to have it there, you'll quite probably need it later.
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; }
}
This is how it works:
Sample object initialization, for testing:
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"},
}
}
});
这篇关于如何将两个可编辑和可更新的DataGridView绑定到一个列表和子列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!