Reputation: 3386
I have the following entities:
public class User
{
public User()
{
Roles = new ObservableCollection<Role>();
}
public int UserId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
}
With this ViewModel:
public class UserManagerViewModel : ObservableObject
{
public ObservableCollection<Role> AllRoles { get; set; }
public UserViewModel()
{
AllRoles = new ObservableCollection<Role>(RoleRepository.GetAll());
}
private User _selectedUser;
public User SelectedUser
{
get { return _selectedUser; }
set
{
if (_selectedUser != value)
{
_selectedUser = value;
RaisePropertyChanged();
}
}
}
...
}
I want to display the SelectedUser
roles in the following way(or anything similar):
<Window.DataContext>
<vm:UserManagerViewModel/>
</Window.DataContext>
<ListBox ItemsSource="{Binding AllRoles}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding ???}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
To what do I need to set the IsChecked
property of the CheckBox
so that it will represent the SelectedUser
roles?
Upvotes: 3
Views: 1204
Reputation: 61379
Assuming that you want to "check" roles that SelectedUser
has.
First we answer the question, "What data does this depend on?" The answer is pretty simple, it depends on the role itself, so we write:
<CheckBox Content="{Binding Name}" IsChecked="{Binding .}"/>
Now clearly, that isn't a bool; so we will need to write a converter for it that checks against a collection. We could do a MultiValueConverter here (as in @Moji's answer), but it's probably easier to expose the collection via a Dependency Property, and bind when creating the converter.
<Window.Resources>
<local:CollectionContainsConverter Collection="{Binding SelectedUser.Roles}"/>
</Window.Resources>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=., Converter={StaticResource CollectionContainsConverter}"/>
And the converter:
public class CollectionContainsConverter : IValueConverter
{
public IEnumerable<object> Collection { get; set; } //This is actually a DP
public object Convert(...)
{
return Collection.Contains(value);
// or possibly, to allow for the Object.Equals override
return Collection.Any(o => o.Equals(value));
}
public object ConvertBack(...)
{
return Binding.DoNothing;
}
}
Having not tested this, you may need to use the second return so it doesn't compare references, and utilize Object.Equals
(or another comparator of your choice) to figure out if the item is in the list.
Upvotes: 1
Reputation: 1240
you can use MultipleBinding and MultipleValueVonverter as below
<Grid>
<Grid.Resources>
<local:RoleValueConverter x:Key="converter"></local:RoleValueConverter>
</Grid.Resources>
<ListBox ItemsSource="{Binding AllRoles}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" >
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource converter}">
<Binding Path="."></Binding>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ListBox}}" Path="DataContext"></Binding>
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
public class RoleValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//values[0] is Role object
//value[1] is UserManagerViewModel
// then you can see if Selected user had Role object return true else return false
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Upvotes: 0