C# MVVM Combobox
In XAML I have a combobox defined as:
<ComboBox x:Name="UsernameComboBox"
ItemsSource="{Binding Users}"
DisplayMemberPath="Username"
SelectedItem="{Binding Path=SelectedName, Mode=TwoWay}"/>
Right now, it doesn't show any default selected item.
I fill the combo box with a list:
public List<User> Users
{
get
{
return _userRepository.RetrieveUsers();
}
}
public List<User> RetrieveUsers()
{
_users = (from Users in _db.Users select Users).ToList();
return _users;
}
The proper Users being the ItemSource for the combobox. then in the XAML I defined SelectedItem and bound it to a property cal开发者_运维问答led Selected name.
In code this looks like:
private User _selectedName;
public User SelectedName
{
get
{
return _selectedName;
}
set
{
if (_selectedName == value) return;
_selectedName = value;
OnPropertyChanged("SelectedName");
}
}
How can I get my combobox to show a selectedItem at startup?
One problem I can see is that each time Users
property is accessed, the RetrieveUsers()
method is invoked which re-runs your database query. This is going to upset your SelectedItem
binding which will expect the list of items bound to the ComboBox
to be unchanged. In other words, it finds the selected item by evaluating the equality of the SelectedItem
against the collection of bound items.
You need to query the database once ...
public YourClassConstructor()
{
_users = _userRepository.RetrieveUsers();
_selectedName = _users[0];
}
public List<User> Users
{
get
{
return _users;
}
}
This will also ensure that the first item is selected.
There are some performance implications you should consider when choosing to bind to a non-observable collection. The update time is significantly faster if you bind to an observable collection instead of a simple list.
You should take a look at using an items source that implements the INotifyCollectionChanged interface, such as an ObservableCollection{T} collection or expose your items source in your view model using ICollectionView. Also take a look at this information about Data Binding in the context of MVVM.
I personally prefer exposing items sources in my view models using ICollectionView. Silverlight provides the PagedCollectionView class, and WPF provides the ListCollectionView class.
public ICollectionView Users
{
get
{
if (_viewModelUsers == null)
{
_viewModelUsers = new PagedCollectionView(_viewModelUsersSource);
}
return _viewModelUsers;
}
}
private ICollectionView _viewModelUsers;
private ObservableCollection<User> _viewModelUsersSource = new ObservableCollection<User>();
You can then use MoveCurrentToFirst() to set the selected item after populating the underlying source collection using a call to your repository.
精彩评论