2013-03-26 65 views
2

我有一個Customer類,我希望在用戶更改Customer.CityInfo屬性的值時收到通知。如何檢測屬性值(引用類型屬性)在c#中更改?

public class City 
{ 
    public long Id {get;set;} 
    public string Code {get;set;} 
} 

public class Customer 
{ 

    private City cityInfo; 
    private string name; 

    public long Id { get; set; } 
    public bool IsCityModified { get; set;} 
    public bool IsCustomerNameModified { get; set; } 

    public string Name 
    { 
     get{ return name;} 
     set 
     { 
      if(name!=value) 
      { 
       IsCustomerNameModified=true; }name=value; 
      } 
     } 
    } 


    public City CityInfo 
    { 
    get 
     { 
      if(cityInfo==null) 
      { 
       cityInfo=new City(); 
      } 
      return cityInfo; 
     } 

     set{ 
      if(this.cityInfo!=value) 
      { 
      IsCityModified =true; 
      } 
      this.cityInfo=value; 
     } 
    } 
} 

public ActionResult Save() 
{ 
    Customer customer=this.currentCustomerSession; 
    if(TryUpdateModel<Customer>(customer)){ 
     UpdateModel<Customer>(customer) 
    } 
    if(customer.IsCustomerNameModified){ 
     //I am able to detect whether the customerName value has been changed in the frontend. 
    } 
    if(customer.IsCityModified){ 
     //I am not able to detect whether the city value has been changed in the frontend. 
    } 
} 

我可以,如果客戶名稱,因爲它的值類型更改標誌(IsCustomerNameModified)設置爲true。但無法檢測參考類型中所做的更改。

任何人都可以幫忙嗎?

+0

用戶如何與應用程序進行通信?通過贏的形式? – Fjodr 2013-03-26 14:37:48

+0

字符串不是值類型,它是(不可變的)引用類型。 – 2013-03-26 14:38:03

+1

我可以問你爲什麼想知道它是否改變?在某些情況下,驗證所有字段是否已更改爲執行較小的更新只需要比更新所有內容更多的時間。但也許你有另一個原因,我不知道:) – 2013-03-26 14:42:33

回答

3

這類問題通常是通過更改通知系統處理的。看到這篇文章:How to: Implement Property Change Notification

段:

public string PersonName 
    { 
     get { return name; } 
     set 
     { 
      name = value; 
      // Call OnPropertyChanged whenever the property is updated 
      OnPropertyChanged("PersonName"); 
     } 
    } 

    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 

使用此模式將幫助您避免需要設置標誌或其他類似的陰謀。現在

+0

我實現你的解決方案如下 private void NotifyPropertyChanged([CallerMemberName] String propertyName =「」) { PropertyChangedEventHandler handler = PropertyChanged; 如果(處理!= NULL){ 處理 (這一點,新PropertyChangedEventArgs(propertyName的)); }} 但是每次的PropertyChanged正在空的時間。我害怕。 ,但OnPropertyChanged()觸發 – Sravan 2013-03-26 15:00:32

+0

@Sravan:仔細閱讀鏈接的文章。您實際上需要添加一個事件處理程序,以便它會觸發。如果沒有人在聽(它是空的)它不會觸發。也請不要將代碼粘貼到註釋中。這是非常難以閱讀。如果您更改了代碼,請將其添加到您的原始問題 – 2013-03-26 15:13:07

0

,我理解正確的問題,我建議做到以下幾點:

City對象添加public bool Changed { get; private set; }屬性。

然後在你的對象的每個屬性,檢查值發生了變化,如果有,然後把Changed標誌設置爲true:

public int Id 
{ 
    { get { return this.id } } 
    { 
     set 
     { 
     if (this.id != value) Changed = true; 
     this.id = value; 
     } 
    } 
} 

它類似於實施IPropertyChanged接口,但是這你確信你只能檢查對象是否被修改過一次。

看來你的對象的引用並沒有改變,所以你只需要檢查它的Changed屬性(如果該對象的引用真的變了,我的先例答案會工作)

+0

我已經嘗試了上述內容,但訪問this.cityInfo.Id本身時this.cityInfo值已更改。所以(this.cityInfo.Id!= value.Id)總是爲false。感謝您的重播。 – Sravan 2013-03-26 14:52:51

+0

取代了我的答案,因爲我最後一次是你在評論 – ppetrov 2013-03-26 15:05:06

0

保羅是正確的,你需要實施INotifyProperty更改。這是一個簡單的例子。這很簡單。

public class BaseViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     private int _number; 

     public BaseViewModel() 
     { 
      PropertyChanged += (o, p) => 
            { 
             //this is the place you would do what you wanted to do 
             //when the property has changed. 
            }; 
     } 

     [NotifyPropertyChangedInvocator] 
     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     public int Number 
     { 
      get { return _number; } 
      set 
      { 
       _number = value; 
       OnPropertyChanged("Number"); 
      } 
     } 
    } 
+0

作出的精度後無關,但這樣做PropertyChanged事件被逮住你每次與模型的實例操作時如選擇它 – 2013-10-16 17:18:38

+0

只是檢查,看它是否在實際上是不同的setter if(_number!= value){...} – Kenn 2013-10-18 00:13:21

0

我同意Paul的回答,但您甚至可能需要重寫City類中的Equals()和GetHashCode()函數。重寫的函數可以檢查代碼和ID是否已經改變。

public override bool Equals(object obj) 
{ 
    City other = obj as City; 

    if ((other != null) && (other.Id == this.Id) && (other.Code == this.Code)) 
    { 
     return (true); 
    } 

    return (false); 
} 

public override int GetHashCode() 
{ 
    return (this.Id^this.Code.GetHashCode()) ; 
} 
0

你可以使用INotifyPropertyChanged,但我想你沒有將對象綁定到某個UI元素。 在這種情況下,如果只需要知道CityInfo屬性是否更改,最簡單的解決方案就是引發自定義事件。

public class Customer 
{ 

    private City cityInfo; 
    private string name; 

    public long Id { get; set; } 
    public bool IsCityModified { get; set;} 
    public event Action<City> OnCityInfoChanged; 
    public bool IsCustomerNameModified { get; set; } 

    public string Name 
    { 
     get{ return name;} 
     set 
     { 
      if(name!=value) 
      { 
       IsCustomerNameModified=true; }name=value; 
      } 
     } 
    } 


    public City CityInfo 
    { 
    get 
     { 
      if(cityInfo==null) 
      { 
       cityInfo=new City(); 
      } 
      return cityInfo; 
     } 

     set{ 
      if(this.cityInfo ==value) 
        return; 
      IsCityModified =true; 
      this.cityInfo=value; 
      if(OnCityInfoChanged != null) 
       OnCityInfoChanged(value); 
     } 
    } 
} 

而且

public ActionResult Save() 
{ 
    Customer customer=this.currentCustomerSession; 
customer.OnCityInfoChanged += new Action<CityInfo>((cityInfo) => {//Do Something with New CityInfo}); 
    if(TryUpdateModel<Customer>(customer)){ 
     UpdateModel<Customer>(customer) 
    } 
    if(customer.IsCustomerNameModified){ 
     //I am able to detect whether the customerName value has been changed in the frontend. 
    } 
    if(customer.IsCityModified){ 
     //I am not able to detect whether the city value has been changed in the frontend. 
    } 
}