Rockin Raul
Rockin Raul

Reputation: 115

Data Binding Custom Class to WPF ComboBox Using DisplayMemberPath

I know this is basic, but I'm making the jump from vb.net to C#, and the approach I was using in vb.net doesn't seem to be working. I've created a .dll with a custom class Service.
In my project, I'm populating an ObservableCollection with instances of Service. I want to display the instances in a combobox using DisplayMemberPath in XAML (WPF).

My instances of Service are populating the ComboBox, but the display for each item is blank; I'm just getting a bunch of blank lines to choose from.

I've tried this with and without implementing INotifyPropertyChanged on the class itself, although I don't think it should be necessary at this point since I'm still pretty much at square 1.

Here's my code:

      <Grid>
        <ComboBox Name="TopService"
                        VerticalAlignment="Top"
                        ItemsSource="{Binding}"
                        DisplayMemberPath="{Binding ServCode}"></ComboBox>
      </Grid>

And here's my code behind:

        public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Execute();
    }
    private void Execute()
    {
        SA.franchiseID = "HOL010";
        ObservableCollection<Service> ocService = Service.InitializeServiceList();
        TopService.DataContext = ocService;
    }
}

And the code for the class (referenced via .dll)

    public class Service : INotifyPropertyChanged
{
    #region INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected void Notify(string propertyName)
    {
        if (this.PropertyChanged != null)
        { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }
    }
    #endregion
    private string servCode;
    public string ServCode
    {
        get { return servCode; }
        set { servCode = value; Notify("ServCode"); }
    }
    public string programCode = "";
    public int roundNum = 0;
    public static ObservableCollection<Service> InitializeServiceList()
    {
        ObservableCollection<Service> oc = new ObservableCollection<Service>();
        using (SA s = new SA())
        {
            s.SqlString = @"select 
ps.serv_code
,pc.prgm_code
,ps.round
from prgmserv as ps 
inner join prgmcd as pc on pc.progdefid = ps.progdefid
where pc.available = 1";
            s.reader = s.command.ExecuteReader();
            Service newService;
            while (s.reader.Read())
            {
                newService = new Service();
                newService.servCode = s.reader["serv_code"].ToString();
                newService.programCode = s.reader["prgm_code"].ToString();
                newService.roundNum = Convert.ToInt32(s.reader["round"].ToString());
                oc.Add(newService);
                newService = null;
            }
            return oc;
        }
    }
}

Upvotes: 2

Views: 1226

Answers (2)

Rockin Raul
Rockin Raul

Reputation: 115

I have also come to realize while attempting to bind items to an ItemsControl, that the difference between a Field and a Property become very important. I have been trying to bind to Fields, which does not work. This is technically not different than in VB.net. But an implicitly defined Property in VB.net looks very much like a Field in C#. All that said, I believe I'm ready to go conquer the world now!

Upvotes: 1

DisplayMemberPath is a string. You don't give it a binding to a property; you just give it a path to a property, which it then looks up by reflection.

Try this:

DisplayMemberPath="ServCode"

What you were doing would make it use the value of ServCode as a DisplayMemberPath; if ServCode is 12, it would look for a property named 12 on each item in the combobox -- not your intent, I'm sure.

Upvotes: 6

Related Questions