BindingList with my class populating a ComboBox us

2019-05-19 04:01发布

问题:

I have a BindingList with my class where I would like to populate a ComboBox using a property of it so when my list changes the ComboBox would change as well.

public class UserAccess
{
    public override string ToString()
    {
        return Access;
    }
    public int AccessId { get; set; }
    public string Access { get; set; }
    public List<string> Command = new List<string>();

    public bool HasCommand(string cmd)
    {
        return this.Command.Any(x => x == cmd);
    }
}

public BindingList<UserAccess> accessList = new BindingList<UserAccess>();

On my form load I assign it to the ComboBox:

myComboBox.DataSource = accessList;

I want to populate the box with Access or with the AccessId as value and Access as the printed name.

Problem is that it will print only the last item of the list to the combobox what am I doing wrong ?

回答1:

Use DisplayMember to specify what field to use for display in the ComboBox.
Make accessList readonly to guarantee that you never recreate a new instance of the list. If you don't make it readonly, this may introduce a subtle bug, if you don't reassign DataSource whenever you recereate accessList.

private readonly BindingList<UserAccess> accessList = new BindingList<UserAccess>();

public Form1()
{
    InitializeComponent();

    comboBox1.ValueMember = "AccessId";
    comboBox1.DisplayMember = "Access";
    comboBox1.DataSource = accessList;
}

private void button1_Click(object sender, EventArgs e)
{
    accessList.Add(new UserAccess { AccessId = 1, Access = "Test1" });
    accessList.Add(new UserAccess { AccessId = 2, Access = "Test2" });
}

If you need to be able to change items properties in accessList (like accessList[0].Access = "Test3") and see the changes reflected in UI, you need to implement INotifyPropertyChanged.

For example:

public class UserAccess : INotifyPropertyChanged
{
    public int AccessId { get; set; }

    private string access;

    public string Access
    {
        get
        {
            return access;
        }

        set
        {
            access = value;
            RaisePropertyChanged("Access");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var temp = PropertyChanged;
        if (temp != null)
            temp(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}