Каков предпочтительный способ связать свойство List объекта в WPF? - PullRequest
3 голосов
/ 15 декабря 2010

Я использую MVVM в WPF в C # .NET.Скажем, у меня есть следующий пример модели:

public class Dealer
{
    public string Name { get; set; }
    public List<Car> Cars { get; set; }
}

public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
}

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

Мой вопрос: как я могу связать список автомобилей с представлением списка, если это свойство объекта Dealer?В частности, что я должен иметь в моем представлении модели?Мне нужно обновить список автомобилей, если я добавлю что-нибудь в коллекцию, поэтому у меня есть ощущение, что мне понадобится ObservableCollection.Тем не менее, это, кажется, приводит к тому, что для каждого дилера создаются две коллекции (List и ObservableCollection), и такое дублирование данных представляется неэффективным как с точки зрения кодирования, так и с точки зрения производительности.Есть идеи?

Ответы [ 3 ]

2 голосов
/ 15 декабря 2010

Мы занимались упаковкой списков моделей в коллекцию ObservableCollection. Эта ObservableCollection обычно также является ViewModel для объекта Child, поэтому мы можем контролировать его представление и при необходимости передавать ViewModel в другое представление. У вас будет два списка, но они будут содержать одинаковые ссылки на объекты. Это может показаться дублированием усилий, но при достойном использовании Наследования вы все равно можете поддерживать СУХОЙ подход. Помните, что идея MVVM состоит в том, чтобы создать абстракцию между вашим представлением и моделью. Может показаться, что вы экономите свои усилия заранее, не оборачивая дочерние объекты, однако мы обнаружили, что почти всегда существует необходимость преобразовать эти дочерние объекты объекты позже.

public class DealerViewModel : ViewBase
{
    // This concept can be wrapped in a ListViewBase for a more DRY approach
    private ObservableCollection<CarViewModel> cars;
    public ObservableCollection<CarViewModel> Cars
    {
        get { return cars; }
        set {
            if (cars == value) return;
            cars = value;
            RaisePropertyChanged("Cars");
        }
    }

    // This concept can be wrapped in a ListViewBase for a more DRY approach
    private CarViewModel selectedCar;
    public CarViewModel SelectedCar
    {
        get { return selectedCar; }
        set {
            if (selectedCar== value) return;
            selectedCar= value;
            RaisePropertyChanged("SelectedCar");
        }
    }

    public DealerViewModel(Dealer dealer)
    {
        // This concept can be wrapped in a ListViewBase for a more DRY approach
        Cars = new ObservableCollection(dealer.Cars.Select(c => new CarViewModel(c)));
    }
}

public class CarViewModel
{
}
2 голосов
/ 15 декабря 2010

Хорошо, во-первых, есть ли причина, по которой вы используете ListView поверх ListBox?Если вы не уверены, какой из них использовать, я бы использовал ListBox.Присвойте один ListBox вашему списку дилеров, сидящему на вашей модели представления, который будет ObservableCollection, если вы собираетесь добавлять / удалять дилеров.Затем привяжите SelectedValue этого ListBox к свойству Dealer в вашей модели представления, которое называется, возможно, SelectedDealer.

Затем создайте второй ListBox, который показывает список автомобилей для выбранного дилера.Свяжите свойство DataContext автомобильного ListBox с SelectedDealer и привяжите ItemsSource к Cars.Тогда ваш автомобиль ListBox будет привязан к коллекции автомобилей, сидящих у выбранного дилера.

Если вы хотите добавлять / удалять автомобили и обновлять пользовательский интерфейс, вам нужно использовать ObservableCollection.Вы не хотите, чтобы ваши бизнес-объекты возвращали ObservableCollections, поэтому это преобразование должно быть выполнено в ваших моделях представления.Возможно, вы можете иметь свойство ObservableCollection в вашей модели представления с именем SelectedCars и привязать к нему окно списка автомобилей.В установщике для SelectedDealer вы можете сделать что-то вроде:

public ObservableCollection<Car> SelectedCars { get; set; }

private Dealer selectedDealer;
public Dealer SelectedDealer
{
  get
  {
    return this.selectedDealer;
  }

  set
  {
    if (this.selectedDealer != value)
    {
      this.selectedDealer = value;
      this.SelectedCars = new ObservableCollection(this.SelectedDealer.Cars);
      OnPropertyChanged(() => this.SelectedDealer);
    }
  }
}

В этом случае вы не установили бы DataContext вашего списка автомобилей на SelectedDealer, DataContext не будет установлен, и представлениеМодель будет использоваться неявно.Затем просто свяжите ItemsSource списка автомобилей со свойством SelectedCars.

0 голосов
/ 15 декабря 2010

лично я бы абстрагировал коллекцию 'cars' в другой объект для примера объекта 'Stock'.я бы никогда не раскрыл список или наблюдаемую коллекцию, поскольку это нарушает инкапсуляцию.я бы выставил иенумерацию методами addtock и removestock на объекте Stock, чтобы описать соответствующее поведение.В модели представления такое поведение будет вызывать соответствующий метод в модели и запускать соответствующие события INotifyPropertyChanged.У объекта Stock будет своя собственная модель представления, поэтому привязка будет к IEnumerable в стандартной модели представления.

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