2010-12-14 3 views
3

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

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. Однако это, по-видимому, приводит к наличию двух коллекций (списка и наблюдаемого набора) для каждого дилера, и с этим дублированием данных кажется неэффективным с точки зрения кодирования и производительности. Есть идеи?

+0

Вы абсолютно правы. Понял, что я не ответил на вопрос, удалил ответ. –

ответ

2

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

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

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

Затем у вас есть второй ListBox, который отображает список автомобилей для выбранного дилера. Привяжите свойство DataContext для машины ListBox к SelectedDealer и привяжите ItemSource к 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 Вашего автомобиля ListBox к SelectedDealer, то DataContext не будет установлен, и вид модели будет использоваться неявно. Затем просто привяжите ItemSource списка автомобилей к свойству SelectedCars.

0

персональный я бы отвлек коллекцию «автомобилей» в другой объект, чтобы использовать объект «Stock». я никогда бы не выставил список или наблюдаемую коллекцию, поскольку это нарушает инкапсуляцию. я бы выставил ienumerable с помощью методов добавления и удаления на объекте Stock, чтобы инкапсулировать соответствующее поведение. В модели представления это поведение должно было бы вызвать соответствующий метод в Модели и запустить соответствующие события INotifyPropertyChanged. У объекта «Акция» будет своя собственная модель представления, поэтому привязка будет к IEnumerable на viewModel.

Смежные вопросы