将TextBox绑定到ListBox SelectedItem

时间:2019-07-27 12:33:12

标签: c# .net winforms binding

我目前正在尝试实施一个相对简单的数据管理应用程序。

我有一个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.SelectedItemmembersList_SelectedIndexChanged(object sender, EventArgs e)事件处理程序中设置为membersList,但随后我必须手动将更改写入Binding中的相应项,这也让我觉得这不是最佳解决方案。

是否有一种方法可以使Binding动态化,即在创建后,我就指示该数据源正在更改?

还是以标准方式更改Bindings的数据源而不删除它并创建一个新的数据源? (或者这实际上是最佳做法?)

(另一件事要提到:我对C#中的System.Windows.Data是陌生的,在寻找解决方案时,我发现显然有两个不同的类,一个在System.Windows.Forms命名空间中,另一个在{{1}}命名空间。我想我是使用后者的类。也许我应该使用另一个类?)

1 个答案:

答案 0 :(得分:0)

如评论中所述,将BindingList(或DataTable)与BindingSource关联可以带来一些有趣的好处。

当修改BindingList的元素之一或将新元素添加到列表中时,所有绑定控件都会自动更新。

您可以使用MovePrevious()MoveNext()MoveFirst()MoveLast()方法来导航BindingList中的元素(还提供了其他有用的方法和事件) ,请参阅有关BindingSource功能的文档。

在此,将BindingList<T>(其中TMember类,如下所示)设置为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));

实际上是这样的:

BindingSource and BindingList

请注意,修改文本框的文本后,实时更新列表框的当前项目。

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}";
}