如何检测c#中的属性值(ReferenceType属性)是否发生了变化?

时间:2013-03-26 14:33:36

标签: c# asp.net-mvc reference-type

我有一个Customer类,我想在用户更改Customer.CityInfo属性的值时收到通知。

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

如果Customer Name因其值类型而更改,我可以将标志(IsCustomerNameModified)设置为true。但无法检测参考类型中所做的更改。

有人可以帮忙吗?

5 个答案:

答案 0 :(得分: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));
      }
  }

使用此模式可以帮助您避免设置标记或其他此类阴谋。

答案 1 :(得分:0)

现在我正确地理解了这个问题,我建议你做以下事情:

public bool Changed { get; private set; }对象中添加City属性。

然后在对象的每个属性中,检查值是否已更改,如果已更改,则将Changed标志置为true:

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

它类似于实现IPropertyChanged接口,但是这样您确定只能检查对象是否被修改过一次。

似乎你的对象的引用没有改变,所以你只需要检查它的Changed属性(如果对象的引用真的改变了,我的先例答案就会起作用)

答案 2 :(得分: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");
            }
        }
    }

答案 3 :(得分: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() ) ;
}

答案 4 :(得分: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.
    }
}