[英]Binding a TextBox to a ListBox SelectedItem
I am currently trying to implement a relatively simple data management app. 我目前正在尝试实现一个相对简单的数据管理应用程序。
I have a class Member
and a BindingList<Member> membersList
, as well as a ListBox
and some TextBox
es. 我有一个类Member
和BindingList<Member> membersList
,以及一个ListBox
和一些TextBox
。
The ListBox
is bound to membersList
. ListBox
绑定到membersList
。
Now I, ideally, want to bind the TextBox
es to ListBox.SelectedItem
, so that whatever element the user has selected in the ListBox
, when they edit a TextBox
the element in membersList
is updated. 现在,理想情况下,现在我想将TextBox
绑定到ListBox.SelectedItem
,以便用户在ListBox
选择的任何元素,当他们编辑TextBox
, membersList
更新membersList
的元素。
I tried just binding the TextBox
es to ListBox.SelectedItem
, but this made the Binding
to the actual element that ListBox.SelectedItem
is referencing at the moment of the binding creation, not whichever item is selected in the ListBox
. 我尝试仅将TextBox
es绑定到ListBox.SelectedItem
,但这使Binding
到ListBox.SelectedItem
在绑定创建时所引用的实际元素上,而不是在ListBox
选择的任何项目。
firstNameTextBox.DataBindings.Add(new Binding("Text",
membersList.SelectedItem, "firstName", false,
DataSourceUpdateMode.OnPropertyChanged));
I actually solved this already by just clearing and recreating the Bindings
for the TextBox
es in the membersList_SelectedIndexChanged(object sender, EventArgs e)
event handler, but this feels very "hacky" and I suspect there is a more standard solution. 我实际上已经通过在membersList_SelectedIndexChanged(object sender, EventArgs e)
事件处理程序中清除并重新创建TextBox
的Bindings
而解决了这个问题,但这感觉非常“棘手”,我怀疑还有更标准的解决方案。
Another idea I had was to just make the Binding
s to a Member temporaryMember
that is set to ListBox.SelectedItem
inside the membersList_SelectedIndexChanged(object sender, EventArgs e)
event handler, but then I have to manually write the changes through to the corresponding item in membersList
which also makes me feel like this isn't the optimal solution. 我的另一个想法是将Binding
s设置为membersList_SelectedIndexChanged(object sender, EventArgs e)
事件处理程序内设置为ListBox.SelectedItem
的Member temporaryMember
,但随后我必须手动将更改写入到相应的项目中membersList
,这也让我觉得这不是最佳解决方案。
Is there a way to make the Binding
dynamic, in the sense that, upon creation, I indicate to it that the DataSource is changing? 有某种方法可以使Binding
动态化,即在创建后我向其指示DataSource正在更改?
Or a standard way the change the Binding
s DataSource without deleting it and creating a new one? 还是以一种标准的方式更改Binding
的DataSource而不删除它并创建一个新的? (Or is this actually best practice?) (或者这实际上是最佳实践吗?)
(Another thing to mention: I am new to Bindings
in C# and while searching for solutions, I found out that there apparently are two different classes, one in the System.Windows.Data
namespace and another in the System.Windows.Forms
namespace. I think I am using the class from the latter. Maybe I should use the other one?) (要提及的另一件事:我是C#中的Bindings
新手,在搜索解决方案时,我发现显然有两个不同的类,一个在System.Windows.Data
命名空间中,另一个在System.Windows.Forms
命名空间中。我想我使用的是后者的类,也许我应该使用另一个?
As described in the comments, associating a BindingList (or a DataTable) with a BindingSource can have some interesting benefits. 如注释中所述,将BindingList (或DataTable)与BindingSource关联可以带来一些有趣的好处。
All bound controls are updated automatically when one of the elements of the BindingList
is modified or a new element is added to the list. 当BindingList
的元素之一被修改或新元素添加到列表中时,所有绑定控件都将自动更新。
You can use the MovePrevious()
, MoveNext()
, MoveFirst()
, MoveLast()
methods to navigate the elements in the BindingList
(other useful methods and events are available, see the Docs about the BindingSource functionality). 您可以使用MovePrevious()
, MoveNext()
, MoveFirst()
, MoveLast()
方法来导航BindingList
的元素(其他有用的方法和事件可用,请参阅有关BindingSource功能的文档)。
Here, a BindingList<T>
(where T
is the Member
class shown below) is set as the DataSource of a BindingSource. 在这里,将BindingList<T>
(其中T
是下面显示的Member
类)设置为BindingSource的DataSource。 Both are Fields of a Form class, this can be modified as needed. 两者都是Form类的Field,可以根据需要进行修改。
The BindingSource is then used as the DataSource of a ListBox. 然后将BindingSource用作ListBox的数据源。
The Text
property of two TextBox controls is then bound, using the BindingSource, to one of the properties of the Member
class. 然后,使用BindingSource将两个TextBox控件的Text
属性绑定到Member
类的属性之一。 This way, the Text property is set to the current Item of the BindingList. 这样,Text属性设置为BindingList的当前Item。 All controls are synchronized : 所有控件均已同步 :
txtMemberName.DataBindings.Add(new Binding("Text", membersSource,
"FirstName", false, DataSourceUpdateMode.OnPropertyChanged));
txtMemberLastName.DataBindings.Add(new Binding("Text", membersSource,
"LastName", false, DataSourceUpdateMode.OnPropertyChanged));
This is how it works, in practice: 实际上是这样的:
Note that the current Item of the ListBox is updated in real time when the Text of a TextBox is modified. 请注意,修改文本框的文本后,将实时更新列表框的当前项目。
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 && frmNew.newMember != null) {
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();
}
}
}
Sample New Member Form: 新会员表格样本:
public partial class frmNewMember : Form
{
public Member newMember;
private void btnSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtMemberName.Text) ||
string.IsNullOrEmpty(txtMemberLastName.Text)) return;
newMember = new Member(txtMemberName.Text, txtMemberLastName.Text);
}
}
Sample Member class: 样本成员类:
[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}";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.