Привязка данных с видом объединения по двум спискам - PullRequest
1 голос
/ 11 февраля 2011

Я знаком с основами привязки данных в wpf. Однако теперь у меня есть проблема, и мне интересно, как ее решить.

Представьте себе следующий вариант использования:

У меня есть глобальная коллекция ObservableCollection под названием «AItems» типа A.
У меня есть несколько объектов типа B, и у каждого есть ObservableCollection "BItems" типа A.
Коллекции BItems могут содержать объекты глобальной коллекции AItems.

Я хочу визуализировать это с помощью ListView.
Каждая строка должна содержать A-объект и флажок.
Я хочу, чтобы ListView показывал все элементы коллекции AItems. Элементы, которые назначены B-объекту, должны быть отмечены флажком. Все остальные флажки должны быть сняты.

Мои вопросы сейчас:
Как мне установить текст данных?
Как сделать так, чтобы при установке флажка этот элемент был вставлен в коллекцию BItems, а при снятии флажка он был удален?

Я надеюсь, что любой может понять мою проблему.

Спасибо за ответы.

Ответы [ 2 ]

3 голосов
/ 11 февраля 2011

Мне не совсем ясно по последней части вашего вопроса.Отчасти это потому, что ваше соглашение об именах сбивает с толку;Я ожидаю, что коллекция с именем BItems будет содержать объекты типа B, а не A.

Так что я собираюсь немного изменить вашу номенклатуру, чтобы не запутаться.Вместо A я буду называть первый класс User, а вместо B я буду называть второй класс Group.Group содержит коллекцию User объектов с именем Users.Глобальные коллекции выглядят так:

List<User> Users;
List<Group> Groups;

Легко определить, входит ли данный User u в какую-либо группу:

return Groups.Where(g => g.Users.Contains(u)).Any();

Легко, но вычислительно дорого, если выесть много групп, и они содержат много пользователей.Мы вернемся к этому через секунду.

Сразу же я вижу, что у одного из ваших вопросов возникла проблема:

Как сделать так, чтобы флажок вставлялсяего элемент в BItems-Collection и снятие отметки удаляет его?

Что произойдет, если я проверю непроверенного пользователя?К какой группе (или группам, поскольку более чем одна группа может содержать пользователя) ее следует добавить?

Поскольку вы говорите, что хотите, чтобы отмеченные элементы были «назначены B-объекту», яПредположим, что пользовательский интерфейс просматривает только одну группу за раз - мы назовем это SelectedGroup.Это хорошо, потому что g.Users.Contains(u) намного дешевле, чем запрос, который я показал выше.

Если это так, то вам нужно обернуть User в класс, который выставляет IsCheckedимущество.Я бы назвал этот класс UserViewModel, так как это то, что он есть.Классу нужно три свойства (как минимум):

public User User { get; set; }

public Group SelectedGroup { get; set; }

public bool IsChecked
{ 
   get { return SelectedGroup.Users.Contains(this.User); } 
   set
   {
      if (value != IsChecked)
      {
         if (IsChecked)
         {
            SelectedGroup.Users.Remove(this.User);
         }
         else
         {
            SelectedGroup.Users.Add(this.User);
         }
      }
   }
}

Ваш ListView связан с ObservableCollection<UserViewModel> с именем, скажем, UserViewModels.Всякий раз, когда установлен SelectedGroup, вам необходимо перестроить эту коллекцию:

UserViewModels = new ObservableCollection<UserViewModel>(
   Users.Select(u => new UserViewModel { User=u, SelectedGroup=SelectedGroup }));

Вы можете избежать перестроения коллекции, реализовав INotifyPropertyChanged в классе UserViewModel и подняв PropertyChanged дляIsChecked свойство всякий раз, когда SelectedGroup изменяется.

Кроме того, вероятно, было бы возможно включить проверку нулевой ссылки в свойство IsChecked, чтобы программа не выдавала исключение, если SelectedGroup или SelectedGroup.Users равно нулю.

0 голосов
/ 11 февраля 2011

Вы можете привязать окно списка к Aitems и использовать конвертер для установки свойства isChecked

<ListBox ItemsSource="{Binding AItems}">
    <ListBox.ItemTemplate>
        <DataTemplate>
                <CheckBox Content="{Binding}" IsChecked="{Binding Mode=OneTime, Converter={StaticResource BItemCheckConverter}}"></CheckBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

public class BItemCheckConverter : IValueConverter
{
    public List<Aitems> BItems { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (BItems.Contains((value as Aitems)) return true;
        else return false
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Я не знаю, как ваша модель объекта, поэтому примите приведенный выше код как есть.

НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...