Search code examples
c#wpfmvvmmvvm-light

Bind combobox items source to certain property of those objects


Say I have have a list of TeamParameter objects that have a name and id property. I want to have a combobox that will show a list of TeamParameter objects but only display the name property of each one in the combobox to the user. Is there a way to bind to that property within the MainWindow.xaml?

Tried dot notation thinking it would work but no.

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
        private List<TeamParameters> _teams;

        public class TeamParameters
        {
            public string Name { get; set; }

            public int Id { get; set; }
        }

        public List<TeamParameters> Teams
        {
            get { return _teams; }
            set { Set(ref _teams, value); }
        }
}

MainWindow.xaml

<Window x:Class="LiveGameApp.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LiveGameApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        DataContext="{Binding Main, Source={StaticResource Locator}}">



    <DockPanel>
        <ComboBox  Name="TeamChoices" ItemsSource="{Binding Team.Name}"  DockPanel.Dock="Top" Height="30" Width="175" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></ComboBox>
    </DockPanel>
</Window>

Solution

  • To point to a particular property on the data model you can specify the member path by setting the DisplayMemberPath:

    <ComboBox  ItemsSource="{Binding Teams}" DisplayMemberPath="Name" />
    

    When you didn't provide a DataTemplate and didn't specify a DisplayMemberPath for the items of an ItemsControl, the control will display the item's string representation by default. This is done by invoking Object.ToString() on each item. Therefore as an alternative you can always override the Object.ToString() of the TeamParameters type (or the item model in general):

    public class TeamParameters
    {
      public override string ToString() => this.Name;
    
      public string Name { get; set; }
    
      public int Id { get; set; }
    }
    

    XAML

    <ComboBox  ItemsSource="{Binding Teams}" />
    

    Or simply provide a DataTemplate:

    <ComboBox ItemsSource="{Binding Teams}">
        <ComboBox.ItemTemplate>
            <DataTemplate DataType="TeamParameters">
                <TextBlock Text="{Binding Name}" /> 
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>