2013-01-04 61 views
1

在具有乾淨模型(不實現像INotifyPropertyChabged的接口)的MVVM應用程序中,視圖模型包含綁定到視圖的屬性,並且這些屬性獲取其值從包含在視圖模型中的模型對象開始,並且應該在視圖更改綁定到這些屬性的控件之一時設置其屬性的值。 這個會徽是什麼時候改變的;更改由綁定視圖模型屬性捕獲,但屬性無法設置模型對象字段,模型不會更改。我需要模型字段接受視圖模型屬性的設置,然後我可以將更新的模型持久化到數據庫中,同時考慮到它是一個乾淨的模型。MVVM:如何使清潔模型的視圖模型集字段保持對數據庫的視圖更改

視圖模型代碼

public class SubsystemDetailsViewModel: INotifyPropertyChanged, ISubsystemDetailsViewModel 
    { 
     #region Fields 
     //Properties to which View is bound 
     private int? _serial; 
     public int? Serial 
     { 
      get { return Subsystem.Serial; } 
      set 
      { 
       //Subsystem.Serial=value; 
       _serial = value; 
       OnPropertyChanged("Serial"); 
      } 
     } 

     private string _type; 
     public string Type 
     { 
      get { return Subsystem.Type; } 
      set 
      { 
       //Subsystem.Type = value; 
       _type = value; 
       OnPropertyChanged("Type"); 
      } 
     } 


     //remaining properties .... 


     #endregion 

     //Service 
     private readonly ISubsystemService _subsystemService; 



     //Reference to the View 
     public ISubsystemDetailsView View { get; set; } 

     //Event Aggregator Event 
     private readonly IEventAggregator eventAggregator; 

     //Commands 
     public ICommand ShowTPGCommand { get; set; } 
     public DelegateCommand UpdateCommand { get; set; } 

     // 
     private bool _isDirty; 

     //Constructor ************************************************************************************************ 
     public SubsystemDetailsViewModel(ISubsystemDetailsView View, ISubsystemService subsystemService, IEventAggregator eventAggregator) 
     { 
      _subsystemService = subsystemService; 

      this.View = View; 
      View.VM = this; 

      //EA-3 
      if (eventAggregator == null) throw new ArgumentNullException("eventAggregator"); 
      this.eventAggregator = eventAggregator; 
      //Commands 
      this.ShowTPGCommand = new DelegateCommand<PreCommissioning.Model.Subsystem>(this.ShowTestPacks); 
      this.UpdateCommand = new DelegateCommand(this.UpdateSubsystem, CanUpdateSubsystem); 


     } 


     //**************************************************************************************************************** 
     //ICommand-3 Event Handler 
     //this handler publish the Payload "SelectedSubsystem" for whoever subscribe to this event 
     private void ShowTestPacks(PreCommissioning.Model.Subsystem subsystem) 
     { 
      eventAggregator.GetEvent<ShowTestPacksEvent>().Publish(SelSubsystem); 
     } 
     //=============================================================================================== 
     private void UpdateSubsystem() 
     { 

      _subsystemService.SaveChanges(Subsystem); 
     } 

     private bool CanUpdateSubsystem() 
     { 
      return _isDirty; 
     } 
     //******************************************************************************************* 
     public void SetSelectedSubsystem(PreCommissioning.Model.Subsystem subsystem) 
     { 
      this.SelSubsystem = subsystem; 

     } 

     //************************************************************************************************************ 
     /// <summary> 
     /// Active subsystem >> the ItemSource for the View 
     /// </summary> 
     private PreCommissioning.Model.Subsystem _subsystem; 
     public PreCommissioning.Model.Subsystem Subsystem 
     { 
      get 
      { 
       //return this._subsystem; 
       GetSubsystem(SelSubsystem.SubsystemNo); 
       return this._subsystem; 

      } 

      set 
      { 
       if (_subsystem != value) 
       { 
        _subsystem = value; 
        OnPropertyChanged("Subsystem"); 
       } 

      } 

     } 



     //Call the Service to get the Data form the Database 
     private void GetSubsystem(string SSNo) 
     { 
      this._subsystem = _subsystemService.GetSubsystem(SSNo); 


     } 





     #region Implementation of INotifyPropertyChanged 
     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string propertyName) 
     { 
      _isDirty = true; 
      UpdateCommand.RaiseCanExecuteChanged(); 

      PropertyChangedEventHandler handler = this.PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
     #endregion 

    } 
} 

子系統的一部分在這裏是其使用GetSubsystem()方法填充模型對象。視圖模型屬性如Serial從模型中獲取它的值,如圖所示。我試圖將其設置爲在屬性的設置部位註釋掉線所示的模型性質,但沒有改變發生在子系統對象,始終保持其原始值

+0

是否有你的屬性設置該模型的屬性行註釋掉的理由......因爲,這將是它不起作用的原因。除此之外,你在輸出窗口中是否有錯誤? – Thelonias

+0

@Ryan:它被註釋掉了,因爲我嘗試了另一種方式來解決這個問題,它工作,但我認爲它不是正確的方式來解決問題 – Hussein

回答

1

如果GetSubsystem每次都返回一個新的子系統,那是你的問題。在您綁定到視圖的屬性的「集合」中,您將調用公共屬性「Subsystem」,而不是您創建的私有字段。因此,您每次從視圖設置屬性時,都會調用Subsystem.get,它調用GetSubsystem(SelSubsystem.SubsystemNo);

我想,在你的ViewModel屬性,你想將其改爲:

//Properties to which View is bound 
public int? Serial 
{ 
    get { return _subsystem.Serial; } 
    set 
    { 
     _subsystem.Serial=value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY 
     OnPropertyChanged("Serial"); 
    } 
} 

public string Type 
{ 
    get { return _subsystem.Type; } 
    set 
    { 
     _subsystem.Type = value; // NOTE THE USE OF THE PRIVATE FIELD RATHER THAN THE PROPERTY 
     OnPropertyChanged("Type"); 
} 
+0

非常感謝,您的想法是正確的,只剩下一個問題:拋出異常@「get {return _subsystem.Serial;}」說「對象引用未設置爲對象的實例」。 _subsystem爲空,但它工作得很好,當我用「get {return Subsystem.Serial;}」替換它僅用於第一個屬性。 – Hussein

+0

因爲_subsystem沒有被設置。您不再調用GetSubsystem,但是當您調用Subsystem.Serial時。從某處調用GetSubsystm(構造函數?),你應該很好 – Thelonias

+0

你又對了。感謝你的幫助。 – Hussein

0

您需要在您的視圖模型爲參考模型和視圖模型會將值傳遞給模型。您的視圖模型將實現INotifyPropertyChanged,並且將成爲視圖的數據環境。在您的視圖模型,寫你的綁定屬性是這樣的:

private string yourProperty; 
public string YourProperty 
{ 
get { return yourProperty; } 
set 
{ 
if (value == yourProperty) 
    return; 
yourProperty= value; 
YOUR_MODEL_REFERENCE.YourProperty= yourProperty; 
this.RaisePropertyChanged(() => this.YourProperty); 
} 
} 
+0

相同的結果,模型不會改變:順便模型字段由服務器填充,從數據庫中抓取這些字段並將其分配給模型。 – Hussein

+0

發佈代碼示例。這是標準的東西,應該很容易修復。此外,您已將服務/模型評論與我混淆了。 –

+0

@@ Big dady:感謝您的幫助。我編輯了我的問題上面附上視圖模型代碼的一部分 – Hussein

相關問題