2016-12-14 387 views
-1

我有一個MVVM模式和綁定集合的問題。我的視圖模型提供了一個收集到的看法,但得到這個集合我用這個:MVVM和業務邏輯層

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

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

當我綁定在這個名單就好像我直接我查看綁定的模型,因爲它們使用相同的參考我的看法。因此,當我編輯Car的一個屬性時,可以直接編輯模型而不使用carServices驗證方法。

什麼是解決此問題的最佳解決方案?

我是否必須將我的模型副本公開給我的視圖,以便不直接從視圖編輯我的模型?

是否必須在我的模型中使用BindingList並使用我的carServices中的ListChanged來驗證每個更改?

+0

可能的重複[如何構建MVVM與集合?](http://stackoverflow.com/questions/7178801/how-do-i-structure-mvvm-with-collections) –

+0

谷歌「mvvm收藏」,你會發現噸的討論和有用的解決方案 –

回答

1

您應該直接在Car類中執行驗證,或者暴露包裝對象而不是將「真實」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,

有了這個解決方案我要創建每類需要外界的驗證一個包裝。它增加了工作,在重構過程中,我們必須編輯類和包裝器。

你怎麼看待這個解決方案是什麼:

  1. 我把我的車的名單中有約束力的列表
  2. 我的服務訂閱這個列表的ListChanged事件
  3. 我的服務實現INotifyDataErrorInfo
  4. 對於此列表中的每個修改都將執行驗證
  5. 如果發生錯誤ErrorsChanged事件被觸發 視圖模型會對此產生偶數t並檢索錯誤數據。
  6. 視圖模型對這個事件進行subsribe並檢索錯誤數據。

例如:

我的服務實現:

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

我的視圖模型

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