简体   繁体   中英

WPF MVVM ComboBox with default selected value

I have this trivial question, but nothing works for me:/ I'm trying to set default selected combobox value from viewmodel. Here's the code:

public class ItemFilter
{
    public int Id { get; set; }
    public string Name { get; set; }
}

In ViewModel:

public MainViewModel()
{
    SelectedItemFilter = ItemFilters[0];
}

public IList<ItemFilter> ItemFilters
{
    get
    {
        IList<ItemFilter> itemFilter = new List<ItemFilter>();
        itemFilter.Add(new ItemFilter() { Id = 0, Name = "All" });
        itemFilter.Add(new ItemFilter() { Id = 1, Name = "One" });
        itemFilter.Add(new ItemFilter() { Id = 2, Name = "Two" });
        return itemFilter;
    }
}

public ItemFilter SelectedItemFilter
{
    get { return _selectedItemFilter; }
    set { SetProperty(ref _selectedItemFilter, value); }
}

In View:

<DataGrid x:Name="DataGridItems"
              EnableRowVirtualization="True"
              ItemsSource="{Binding ItemCollection}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Foo" Binding="{Binding Path=SizeComment}" IsReadOnly="True" Width="120">
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="{Binding DataContext.ItemFilters, RelativeSource={RelativeSource AncestorType=Window}}"
                                  SelectedItem="{Binding DataContext.SelectedItemFilter, RelativeSource={RelativeSource AncestorType=Window}, Mode=TwoWay}"
                                  DisplayMemberPath="Name" />
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

What am I missing?

The first obvious reason is that ItemFilters is created on every request. So SelectedItemFilter = ItemFilters[0]; creates a list of filters and then assign the first one to SelectedItemFilter . When ComboBox requests list of filters it gets a different list of filters. So SelectedItemFilter cannot be found in ComboBox items list. There are two solutions:

  1. A better one -> instatiate ItemFilters once in a constructor.
  2. If 1. is not applicable then override Equals() and GetHashCode() in ItemFilter class

As @Zbigniew suggests creating a new List in the getter of a property is a bad idea.

The constructor of your MainViewModel will create one List<ItemFilter> and set the SelectedItemFilter to the first ItemFilter object in this one and then there will be another List<ItemFilter> created when the binding in the view is resolved and the SelectedItemFilter instance won't be in this new list. That's why you don't get any item selected in the ComboBox .

You should create the source collection once :

public MainViewModel()
{
    IList<ItemFilter> itemFilter = new List<ItemFilter>();
    itemFilter.Add(new ItemFilter() { Id = 0, Name = "All" });
    itemFilter.Add(new ItemFilter() { Id = 1, Name = "One" });
    itemFilter.Add(new ItemFilter() { Id = 2, Name = "Two" });
    ItemFilters = itemFilter;

    SelectedItemFilter = itemFilter[0];
}

public IList<ItemFilter> ItemFilters { get; }

public ItemFilter SelectedItemFilter
{
    get { return _selectedItemFilter; }
    set { SetProperty(ref _selectedItemFilter, value); }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM