Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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 ListBoxand some TextBoxes.

The ListBox is bound to membersList.

Now I, ideally, want to bind the TextBoxes to ListBox.SelectedItem, so that whatever element the user has selected in the ListBox, when they edit a TextBox the element in membersListis updated.

I tried just binding the TextBoxes 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 TextBoxes 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 Bindings 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 Bindings 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?)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
159 views
Welcome To Ask or Share your Answers For Others

1 Answer

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:

BindingSource and BindingList

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...