我目前正在尝试实施一个相对简单的数据管理应用程序。
我有一个Member
和一个BindingList<Member> membersList
班,还有一个ListBox
和一些TextBox
个班。
ListBox
已绑定到membersList
。
现在,理想情况下,我想将TextBox
绑定到ListBox.SelectedItem
,以便用户在编辑ListBox
时在TextBox
中选择的任何元素membersList
中的元素已更新。
我尝试仅将TextBox
绑定到ListBox.SelectedItem
,但这使Binding
成为绑定创建时ListBox.SelectedItem
所引用的实际元素, ListBox
中没有选择任何一项。
firstNameTextBox.DataBindings.Add(new Binding("Text",
membersList.SelectedItem, "firstName", false,
DataSourceUpdateMode.OnPropertyChanged));
我实际上已经通过在Bindings
事件处理程序中为TextBox
es清除并重新创建membersList_SelectedIndexChanged(object sender, EventArgs e)
来解决了这个问题,但这感觉非常“棘手”,我怀疑其中有一个更标准的解决方案。
我的另一个想法是将Binding
变成Member temporaryMember
,该ListBox.SelectedItem
在membersList_SelectedIndexChanged(object sender, EventArgs e)
事件处理程序中设置为membersList
,但随后我必须手动将更改写入Binding
中的相应项,这也让我觉得这不是最佳解决方案。
是否有一种方法可以使Binding
动态化,即在创建后,我就指示该数据源正在更改?
还是以标准方式更改Bindings
的数据源而不删除它并创建一个新的数据源? (或者这实际上是最佳做法?)
(另一件事要提到:我对C#中的System.Windows.Data
是陌生的,在寻找解决方案时,我发现显然有两个不同的类,一个在System.Windows.Forms
命名空间中,另一个在{{1}}命名空间。我想我是使用后者的类。也许我应该使用另一个类?)
答案 0 :(得分:0)
如评论中所述,将BindingList(或DataTable)与BindingSource关联可以带来一些有趣的好处。
当修改BindingList
的元素之一或将新元素添加到列表中时,所有绑定控件都会自动更新。
您可以使用MovePrevious()
,MoveNext()
,MoveFirst()
,MoveLast()
方法来导航BindingList
中的元素(还提供了其他有用的方法和事件) ,请参阅有关BindingSource功能的文档。
在此,将BindingList<T>
(其中T
是Member
类,如下所示)设置为BindingSource的数据源。两者都是Form类的Field,可以根据需要进行修改。
然后将BindingSource用作ListBox的数据源。
然后使用BindingSource将两个TextBox控件的Text
属性绑定到Member
类的属性之一。这样,Text属性设置为BindingList的当前Item。所有控件都是同步的:
txtMemberName.DataBindings.Add(new Binding("Text", membersSource,
"FirstName", false, DataSourceUpdateMode.OnPropertyChanged));
txtMemberLastName.DataBindings.Add(new Binding("Text", membersSource,
"LastName", false, DataSourceUpdateMode.OnPropertyChanged));
实际上是这样的:
请注意,修改文本框的文本后,实时更新列表框的当前项目。
BindingList<Member> members = null;
BindingSource membersSource = null;
public partial class frmMembers : Form
{
public frmMembers() {
InitializeComponent();
InitializeDataBinding();
}
private void InitializeDataBinding()
{
members = new BindingList<Member>();
membersSource = new BindingSource(members, null);
lstBoxMembers.DataSource = membersSource;
txtMemberName.DataBindings.Add(new Binding("Text", membersSource,
"FirstName", false, DataSourceUpdateMode.OnPropertyChanged));
txtMemberLastName.DataBindings.Add(new Binding("Text", membersSource,
"LastName", false, DataSourceUpdateMode.OnPropertyChanged));
}
private void btnAddMember_Click(object sender, EventArgs e)
{
var frmNew = new frmNewMember();
if (frmNew.ShowDialog() == DialogResult.OK) {
members.Add(frmNew.newMember);
}
}
private void btnMovePrevious_Click(object sender, EventArgs e)
{
if (membersSource.Position > 0) {
membersSource.MovePrevious();
}
else {
membersSource.MoveLast();
}
}
private void btnMoveNext_Click(object sender, EventArgs e)
{
if (membersSource.Position == membersSource.List.Count - 1) {
membersSource.MoveFirst();
}
else {
membersSource.MoveNext();
}
}
}
示例新会员表格:
public partial class frmNewMember : Form
{
public Member newMember;
private void btnSave_Click(object sender, EventArgs e)
{
if (txtMemberName.Text == string.Empty || txtMemberLastName.Text == string.Empty) return;
newMember = new Member(txtMemberName.Text, txtMemberLastName.Text);
}
}
示例成员类:
[Serializable()]
public class Member
{
public Member() { }
public Member(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() => $"{this.FirstName} {this.LastName}";
}