将TextBox绑定到ListBox SelectedItem [英] Binding a TextBox to a ListBox SelectedItem
问题描述
我目前正在尝试实现一个相对简单的数据管理应用程序。
我有一个类 Member
和 BindingList< Member> MembersList
,以及 ListBox
和一些 TextBox
es。
ListBox
绑定到 membersList
。
现在,理想情况下,我想将 TextBox
es绑定到 ListBox.SelectedItem
,这样,当用户在<$ c $中编辑 TextBox
中的元素时,用户在 ListBox
中选择的任何元素c> membersList 已更新。
我尝试将 TextBox
es绑定到 ListBox.SelectedItem
,但这将 Binding
绑定到 ListBox.SelectedItem
在绑定创建时正在引用,而不是在 ListBox
中选择的任何项目。
firstNameTextBox.DataBindings.Add(new Binding( Text,
MembersList.SelectedItem, firstName,false,
DataSourceUpdateMode.OnPropertyChanged));
我实际上已经通过清除并重新创建 Bindings $而解决了这个问题在
membersList_SelectedIndexChanged(object sender,EventArgs e)
事件处理程序中的 TextBox
es的c $ c>
我的另一个想法是使 Binding
到 member临时成员
,该成员在 membersList_SelectedIndexChanged()中设置为
事件处理程序,但随后我必须手动将更改写入 ListBox.SelectedItem
。对象发送者,EventArgs e) membersList
中的相应项
在某种意义上,有没有办法使 Binding
动态化?
还是以标准方式更改 Binding
s数据源没有删除它并创建一个新的? (或者这实际上是最佳实践吗?)
(另一件事要提到:我对C#中的 Bindings
是陌生的在寻找解决方案时,我发现显然有两个不同的类,一个在 System.Windows.Data
命名空间中,另一个在 System中.Windows.Forms
命名空间。我想我正在使用后者的类。也许我应该使用另一个类?)
如注释中所述,将
请注意,当列表中的文本文本框已修改。
BindingList< Member> ;成员= null;
BindingSource MembersSource = null;
公共局部类frmMembers:表单
{
public frmMembers(){
InitializeComponent();
InitializeDataBinding();
}
private void InitializeDataBinding()
{
成员= new BindingList< Member>();
MembersSource = new BindingSource(成员,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);
}
}
私人无效btnMovePrevious_Click(对象发送方,EventArgs e)
{
if(membersSource.Position> 0){
MembersSource.MovePrevious();
}
else {
MembersSource.MoveLast();
}
}
私人无效btnMoveNext_Click(对象发送者,EventArgs e)
{
if(membersSource.Position == MembersSource.List.Count- 1){
MembersSource.MoveFirst();
}
else {
MembersSource.MoveNext();
}
}
}
示例新成员表格:
公共部分类frmNewMember:表格
{
public成员newMember;
私人无效btnSave_Click(对象发送方,EventArgs e)
{
if(string.IsNullOrEmpty(txtMemberName.Text)||
string.IsNullOrEmpty(txtMemberLastName.Text ))返回;
newMember =新成员(txtMemberName.Text,txtMemberLastName.Text);
}
}
示例成员类:
[Serializable()]
公共类成员
{
public Member(){}
public Member(字符串firstName,字符串lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
公共字符串FirstName {get;组; }
公用字串LastName {get;组; }
公共替代字符串ToString()=> $ {this.FirstName} {this.LastName};
}
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.
The ListBox
is bound to 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.
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
.
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.
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.
Is there a way to make the Binding
dynamic, in the sense that, upon creation, I indicate to it that the DataSource is changing?
Or a standard way the change the Binding
s DataSource without deleting it and creating a new one? (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?)
As described in the comments, associating a BindingList (or a DataTable) with a BindingSource can have some interesting benefits.
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.
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).
Here, a BindingList<T>
(where T
is the Member
class shown below) is set as the DataSource of a BindingSource. Both are Fields of a Form class, this can be modified as needed.
The BindingSource is then used as the DataSource of a ListBox.
The Text
property of two TextBox controls is then bound, using the BindingSource, to one of the properties of the Member
class. This way, the Text property is set to the current Item of the BindingList. 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}";
}
这篇关于将TextBox绑定到ListBox SelectedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!