2016-12-14 3 views
-1

У меня проблема с коллекцией MVVM и сборкой связывания. Моя ViewModel предоставляет коллекцию View, но чтобы получить эту коллекцию я использую это:MVVM & business logic Layer

public BindingList<Car> BindingListCars { get; set; } 

public CarsVm() 
{ 
    BindingListVoiture = carServices.ListCars; 
} 

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

Какое следует решить проблему?

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

Должен ли я использовать BindingList в моей модели и подписчике на ListChanged в моем carServices для проверки каждого изменения?

+0

Возможный дубликат [Как создать MVVM с коллекциями?] (http://stackoverflow.com/questions/7178801/how-do-i-structure-mvvm-with-collections) –

+0

Google "mvvm collections", вы найдете массу обсуждений и полезных решений –

ответ

1

Вы должны либо выполнить валидацию непосредственно в самом классе Car, либо выставить объекты-обертки, а не подвергать объект «реальным» автомобилям виду.

Следующий пример код должен дать вам представление о том, что я имею в виду:

//the "pure" model class: 
public class Car 
{ 
    public string Model { get; set; } 
} 


public class CarService 
{ 
    public List<CarWrapper> ListCar() 
    { 
     List<Car> cars = new List<Car>(); //get your Car objects... 

     return cars.Select(c => new CarWrapper(c, this)).ToList(); 
    } 

    public bool Validate() 
    { 
     // 
     return true; 
    } 
} 

public class CarWrapper 
{ 
    private readonly Car _model; 
    CarService _service; 
    public CarWrapper(Car model, CarService service) 
    { 
     _model = model; 
     _service = service; 
    } 

    //create a wrapper property for each property of the Car model: 
    public string Model 
    { 
     get { return _model.Model; } 
     set 
     { 
      if(_service.Validate()) 
       _model.Model = value; 
     } 
    } 
} 

Очевидно, что если вы разоблачить IEnumerable < Автомобиля > из модели представления для зрения, чтобы связать, вы эффективно обходя любые проверки который выведен за пределы класса Car, если представление может установить любые свойства класса Car.

0

Спасибо за ваш ответ MM8,

С этим решением я должен создать одну обертку на класс, который нужно вне проверки. Это добавляет работу, и в процессе рефакторинга мы должны редактировать класс и Wrapper.

Что вы думаете об этом решении:

  1. Я положил список автомобиля в обязательном списке
  2. Моя служба подписки на ListChanged события этого списка
  3. Моя служба реализации INotifyDataErrorInfo
  4. Для каждой модификации в этом списке выполняется проверка
  5. При возникновении ошибки возникает событие ErrorsChanged Модель представления относится к этому четному t и получить данные об ошибке.
  6. Модель просмотра относится к этому событию и извлекает данные об ошибках.

Например:

Мои услуги реализация:

public class VehicleServices : INotifyDataErrorInfo 
{ 

    private BindingList<Vehicle> _bindingListCar 
    public BindingList<Vehicle> BindingListCar 
    { 
     get return _bindingListCar; 
    } 

    private readonly Dictionary<string, ICollection<string>> 
     _validationErrors = new Dictionary<string, ICollection<string>>(); 

    //INotifyDataErrorInfo implementation 

    public IEnumerable GetErrors(string propertyName) 
    public bool HasErrors 
    private void RaiseErrorsChanged(string propertyName) 

    public VehicleServices() 
    { 
     _bindingListCar = GetVehicles(); 
     _bindingListCar.ListChanged += BindingListVehicleChanged; 
    } 

    private void BindingListVehicleChanged(object sender, ListChangedEventArgs e) 
    { 
     //Only modification is managed 
     if (e.ListChangedType != ListChangedType.ItemChanged) return; 
     switch(e.PropertyDescriptor.Name) 

     //Validate each property 

     //if there is ErrorsChanged is raised 
    } 
} 

И мой ViewModel

public class CarVm : BindableBase 
{ 

     private ICollection<string> _errors; 

     public ICollection<string> Error 
     { 
     get 
     { 
      return _errors; 
     } 
     set 
     { 
      SetProperty(ref _errors, value); 
     } 
     } 
     private VehicleServices _carServices; 

     public BindingList<Vehicle> BindingListCar { get; set; } 

     public CarVm(VehicleServices carServices) 
     { 
      _carServices = carServices; 
      BindingListCar = new BindingList<Vehicle>(_carServices.BindingListCar); 
      _carServices.ErrorsChanged += _carServices_ErrorsChanged; 
     } 

     private void _carServices_ErrorsChanged(object sender, DataErrorsChangedEventArgs e) 
     { 
      Error = _carServices.ValidationErrors[e.PropertyName]; 
     } 
} 

Как вы думаете, что это хорошая практика?

+0

Это звучит разумно, за исключением что это элемент управления представлением, а не служба, которая должна реализовать интерфейс INotifyDataError. – mm8

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