Brian Var
Brian Var

Reputation: 6227

Binding to ComboBox displays Model name instead of property contents

I've set up the binding for a combo box using a property in the ViewModel. But when I debug the app on a device, the contents of the combo box is just the Model name for each index like LC_Points.Model.Grade.

To debug this issue, I've gone through the following checks:

Does anyone know how to fix this binding issue?

The ViewModel containing the Lists is set up like this:

namespace LC_Points.ViewModel
{

    public class MainViewModel : ViewModelBase
    {

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            //call methods to initilise list data
            GetGradeTypes();
            GetSubjectTypes();

        }


        public List<Grade> grades { get; set; }
        public List<Grade> subjects { get; set; }

        public void GetGradeTypes()
        {
            List<Grade> gradeList = new List<Grade>();

            // Adding Grades to List
            gradeList.Add(new Grade { grade = "A1" });
            gradeList.Add(new Grade { grade = "A2" });
            gradeList.Add(new Grade { grade = "B1" });
            gradeList.Add(new Grade { grade = "B2" });
            gradeList.Add(new Grade { grade = "B3" });
            gradeList.Add(new Grade { grade = "C1" });
            gradeList.Add(new Grade { grade = "C2" });
            gradeList.Add(new Grade { grade = "C3" });
            gradeList.Add(new Grade { grade = "D1" });
            gradeList.Add(new Grade { grade = "D2" });
            gradeList.Add(new Grade { grade = "D3" });
            gradeList.Add(new Grade { grade = "E,F,NG" });
            gradeList.Add(new Grade { grade = "Pass" });
            gradeList.Add(new Grade { grade = "Merit" });
            gradeList.Add(new Grade { grade = "Distinction" });


            grades = gradeList;

        }


        public void GetSubjectTypes()
        {
            List<Grade> subjectList = new List<Grade>();

            // Adding Subjects to List
            subjectList.Add(new Grade { subject = "Accounting" });
            subjectList.Add(new Grade { subject = "Agricultural Economics" });
            subjectList.Add(new Grade { subject = "Agricultural Science" });
            subjectList.Add(new Grade { subject = "Ancient Greek" });
            subjectList.Add(new Grade { subject = "Applied Math" });
            subjectList.Add(new Grade { subject = "Arabic" });
            subjectList.Add(new Grade { subject = "Art" });
            subjectList.Add(new Grade { subject = "Artistic & Creative Group" });
            subjectList.Add(new Grade { subject = "Biology" });
            subjectList.Add(new Grade { subject = "Business" });
            subjectList.Add(new Grade { subject = "Business Group" });
            subjectList.Add(new Grade { subject = "Chemistry" });
            subjectList.Add(new Grade { subject = "Classical Studies" });
            subjectList.Add(new Grade { subject = "Construction Studies" });
            subjectList.Add(new Grade { subject = "Design & Comm Graphics" });
            subjectList.Add(new Grade { subject = "Economics" });
            subjectList.Add(new Grade { subject = "Engineering" });
            subjectList.Add(new Grade { subject = "English" });
            subjectList.Add(new Grade { subject = "French" });
            subjectList.Add(new Grade { subject = "Geography" });
            subjectList.Add(new Grade { subject = "German" });
            subjectList.Add(new Grade { subject = "Hebrew Studies" });
            subjectList.Add(new Grade { subject = "History" });
            subjectList.Add(new Grade { subject = "Home Economics" });
            subjectList.Add(new Grade { subject = "Irish" });
            subjectList.Add(new Grade { subject = "Italian" });
            subjectList.Add(new Grade { subject = "Japanese" });
            subjectList.Add(new Grade { subject = "Languages & Humanities" });
            subjectList.Add(new Grade { subject = "Latin" });
            subjectList.Add(new Grade { subject = "Link Modules" });
            subjectList.Add(new Grade { subject = "Mathematics" });
            subjectList.Add(new Grade { subject = "Music" });
            subjectList.Add(new Grade { subject = "Other Language" });
            subjectList.Add(new Grade { subject = "Physics" });
            subjectList.Add(new Grade { subject = "Physics & Chemistry" });
            subjectList.Add(new Grade { subject = "Practical Group" });
            subjectList.Add(new Grade { subject = "Religious Education" });
            subjectList.Add(new Grade { subject = "Russian" });
            subjectList.Add(new Grade { subject = "Science Group" });
            subjectList.Add(new Grade { subject = "Social Group" });
            subjectList.Add(new Grade { subject = "Spanish" });
            subjectList.Add(new Grade { subject = "Technology" });

            subjects = subjectList;

        }

    }
}

And I've set up the binding in the MainPage View like this:

<Page x:Class="LC_Points.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:LC_Points"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
      DataContext="{Binding Source={StaticResource Locator}}"
      mc:Ignorable="d">



    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40*" />
            <RowDefinition Height="20*" />
            <RowDefinition Height="30*" />
            <RowDefinition Height="30*" />
            <RowDefinition Height="20*" />
            <RowDefinition Height="20*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4.5*" />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>


        <ComboBox x:Name="subjectCmbBx"
                  Grid.Row="1"
                  Grid.ColumnSpan="2"
                  Width="174"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  ItemsSource="{Binding subjects}" />
        <ComboBox x:Name="gradeCmbBx"
                  Grid.Row="1"
                  Grid.Column="0"
                  Grid.ColumnSpan="2"
                  Width="70"
                  HorizontalAlignment="Right"
                  ItemsSource="{Binding grades}" />
    </Grid>

</Page>

The output during debug looks like this:

Debug combo box

Upvotes: 0

Views: 235

Answers (2)

Rob Caplan - MSFT
Rob Caplan - MSFT

Reputation: 21889

You need to tell the ComboBox how to display its items. Otherwise it will just call ToString() on the bound item and display something wonky.

There are three ways to get reasonable output:

  1. Define a reasonable ToString() on your DataObject. This is a good idea even if you do one of the others since Narrator will read this if you don't otherwise set accessibility information.

  2. Define the DisplayMemberPath on the ComboBox to point to the property you want displayed.

<ComboBox x:Name="subjectCmbBx"
          Grid.Row="1"
          Grid.ColumnSpan="2"
          Width="174"
          HorizontalAlignment="Left"
          VerticalAlignment="Top"
          DisplayMemberPath="Name"
          ItemsSource="{Binding subjects}" />
  1. Define an ItemTemplate for the ComboBox to completely control how each item is displayed. This will allow displaying multiple properties from the bound object, formatting, and a much better UI than just plain text. You can generate an empty template by right clicking on the ComboBox in the designer and choosing Edit Additional Templates.Edit Generated Items (ItemTemplate)... then filling it out as desired:
<ComboBox x:Name="subjectCmbBx"
          Grid.Row="1"
          Grid.ColumnSpan="2"
          Width="174"
          HorizontalAlignment="Left"
          VerticalAlignment="Top"
          ItemsSource="{Binding subjects}" >
    <ComboBox.Resources>
        <DataTemplate x:Key="DataTemplate1">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Image Source="{Binding Picture}" Grid.Column="0" />
                <TextBlock Text="{Binding Name}" Grid.Column="1" />
            </Grid>
        </DataTemplate>
    </ComboBox.Resources>
    <ComboBox.ItemTemplate>
        <StaticResource ResourceKey="DataTemplate1"/>
    </ComboBox.ItemTemplate>
</ComboBox>

I'd recommend #1 (as a minimum for accessibility) and #3 for most cases.

Upvotes: 1

user2588666
user2588666

Reputation: 851

Unless you provide a DisplayMemberPath (https://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.displaymemberpath%28v=vs.110%29.aspx), which is what I would recommend doing, then it will use the provided implementation of Grade::ToString(). So, you could alternatively override that.

Upvotes: 1

Related Questions