WPF привязка к детской коллекции

82
11

У меня есть следующие объекты:


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; }
}


С помощью этой 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();
}
}
}

...
}


Я хочу показать роли SelectedUser следующим образом (или что-то подобное):


<Window.DataContext>
<vm:UserManagerViewModel/>
</Window.DataContext>
<ListBox ItemsSource="{Binding AllRoles}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding ???}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Для чего мне нужно установить свойство IsChecked для CheckBox, чтобы оно представляло роли SelectedUser?

спросил(а) 2014-10-21T18:53:00+04:00 6 лет назад
1
Решение
58

Предполагая, что вы хотите "проверить" роли, которые SelectedUser имеет.


Сначала мы ответим на вопрос: "Какими данными это зависит?" Ответ довольно прост, он зависит от самой роли, поэтому мы пишем:


<CheckBox Content="{Binding Name}" IsChecked="{Binding .}"/>

Теперь ясно, что это не bool; поэтому нам нужно будет написать конвертер для него, который проверяет коллекцию. Мы могли бы сделать MultiValueConverter здесь (как в ответе @Moji), но, вероятно, проще разоблачить коллекцию через Свойство зависимостей и привязать при создании конвертера.

<Window.Resources>
<local:CollectionContainsConverter Collection="{Binding SelectedUser.Roles}"/>
</Window.Resources>

<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=., Converter={StaticResource CollectionContainsConverter}"/>


И конвертер:


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;
}
}


Не тестировав это, вам может понадобиться использовать второй возврат, чтобы он не сравнивал ссылки и использовал Object.Equals (или другой компаратор по вашему выбору), чтобы выяснить, находится ли элемент в списке.

ответил(а) 2014-10-21T19:38:00+04:00 6 лет назад
41

вы можете использовать MultipleBinding и MultipleValueVonverter, как показано ниже

  <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();
}
}

ответил(а) 2014-10-21T19:34:00+04:00 6 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема