1
votes

I am trying to bind a list to a ComboBox and use displaymemberpath to display the values.

This is my XAML:

<ComboBox x:Name="ComboBoxCommissieGroep" 
           ItemsSource="{Binding Commissies}" 
           DisplayMemberPath="CommissieGroep">

ViewModel:

My ViewModel retreives a list of "Commissies"

private async Task LoadData()
{
    commissies = new ObservableCollection<object>(await LoginBLL.GetCommissiesList());
}

Model:

public class InloggenBO : ObservableObject
{
    private int lidNummer;

    public int LidNummer
    {
        get => lidNummer;
        set
        {
            lidNummer = value;
            NotifyPropertyChanged();
        }
    }

    private string commissieGroep;

    public string CommissieGroep
    {
        get => commissieGroep;
        set
        {
            commissieGroep = value;
            NotifyPropertyChanged();
        }
    }

    private string wachtwoord;

    public string Wachtwoord
    {
        get => wachtwoord;
        set
        {
            wachtwoord = value;
            NotifyPropertyChanged();
        }
    }
}

My code database method: The method creates a list of a dataset that has been retrieved from the database. That is why it is of type object and not InloggenBO

protected Task<List<object>> ExecuteReader(string SqlString)
{
    // Read to dataset
    DataSet dataset = new DataSet();

    using (var conn = new SqlConnection(ConnectionString))
    using (var adapter = new SqlDataAdapter(new SqlCommand(SqlString, conn)
    {
        // Set commandtype
        CommandType = CommandType.Text
    }))
    {
        // Open connection
        conn.Open();
        // Fill dataset
        adapter.Fill(dataset);
        // Close connection
        conn.Close();
    }

    return Task.FromResult(ToList(dataset));
}

Method that creates the list object

private List<object> ToList(DataSet dataSet)
{
    var list = new List<object>();

    foreach (var dataRow in dataSet.Tables[0].Rows)
    {
        list.Add(dataRow);
    }
    return list;
}

I have set my DataContext to the viewmodel and I know that the binding works because in my combobox without the displaymemberpath it says: "System.Data.Datarow". So what do I have to put in the displaymemberpath so that I can show its value?

2
Why is your ObservableCollection of type object when it should be of type InloggenBO presumably ? - auburg
Also in your XAML you're binding to Commissies but your vm you have a property (i assume) called commissies - auburg
@auburg I edited my question of how I retrieve my data, so that you know why I have an ObservableCollection of type Object - Brum
It seems like your ToList(dataset) returns a List<DataRow> - so why should a DataRow object know anything about your InloggenBO class? - Rand Random
Because you're binding to a plain object, there's no CommissieGroep property. You should be binding to a list of objects that have that property name for it to work. - auburg

2 Answers

1
votes

The Binding process which is done by the system is done in two parts. The first part is to a target object, and I mean object for its unknown to it, that object is supplied by the DataContext of the control.

If I control does not have a DataContext set, it inherits the parent control as specified in the XAML and if it is also null, that process repeats itself until ultimately the page's datacontext is taken.

Step 2 of binding is when that object is not null, it then reflects to the property from the binding hint given in the binding statement itself.


So in your case it is looking for a property named Commissies off the datacontext. If that property is not null and is a list, the combobox after a successful binding to a list then tries to find and show a property named CommissieGroep in each row to be shown.

Which in the case of the Combobox there are three things which have to be in line for a proper showing of data.

It appears that you do not have the right list (or observable list) of types expected to do a proper binding and showing of data; fixing that will resolve the issue.

1
votes

You could change your ToList method to this:

private List<InloggenBO> ToList(DataSet dataSet)
{
    //new list of InloggenBO instead of objects
    var list = new List<InloggenBO>();

    foreach (var dataRow in dataSet.Tables[0].Rows)
    {
        //create a new instance of InloggenBO
        var item = new InloggenBO();
        //this assumes that the column is named as the member
        item.CommissieGroep = dataRow["CommissieGroep"].ToString(); 
        //fill the other members

        //add the instane of InloggenBO to the list
        list.Add(item);
    }

    return list;
}

But, as @Andy mentioned you should consider using an ORM like Entity Framework.