[英]Raise an event in main whenever a variable's value changed in a class in c#?
[英]Raise an event whenever a property's value changed?
有一个属性,名为ImageFullPath1
public string ImageFullPath1 {get; set; }
每当其值发生变化时,我都会触发一个事件。 我知道改变INotifyPropertyChanged
,但我想用事件来做。
INotifyPropertyChanged
接口是通过事件实现的。 该接口只有一个成员PropertyChanged
,这是消费者可以订阅的事件。
Richard 发布的版本不安全。 下面是如何安全地实现这个接口:
public class MyClass : INotifyPropertyChanged
{
private string imageFullPath;
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, e);
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public string ImageFullPath
{
get { return imageFullPath; }
set
{
if (value != imageFullPath)
{
imageFullPath = value;
OnPropertyChanged("ImageFullPath");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
请注意,这会执行以下操作:
抽象属性更改通知方法,以便您可以轻松地将其应用于其他属性;
在尝试调用它之前制作PropertyChanged
委托的副本(不这样做将创建竞争条件)。
正确实现INotifyPropertyChanged
接口。
如果您想为正在更改的特定属性另外创建通知,您可以添加以下代码:
protected void OnImageFullPathChanged(EventArgs e)
{
EventHandler handler = ImageFullPathChanged;
if (handler != null)
handler(this, e);
}
public event EventHandler ImageFullPathChanged;
然后在OnImageFullPathChanged(EventArgs.Empty)
OnPropertyChanged("ImageFullPath")
行之后添加OnImageFullPathChanged(EventArgs.Empty)
行。
由于我们有 .Net 4.5,因此存在CallerMemberAttribute
,它允许删除源代码中属性名称的硬编码字符串:
protected void OnPropertyChanged(
[System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public string ImageFullPath
{
get { return imageFullPath; }
set
{
if (value != imageFullPath)
{
imageFullPath = value;
OnPropertyChanged();
}
}
}
我使用与 Aaronaught 大致相同的模式,但是如果您有很多属性,最好使用一些通用方法魔术来使您的代码更加DRY
public class TheClass : INotifyPropertyChanged {
private int _property1;
private string _property2;
private double _property3;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null) {
handler(this, e);
}
}
protected void SetPropertyField<T>(string propertyName, ref T field, T newValue) {
if(!EqualityComparer<T>.Default.Equals(field, newValue)) {
field = newValue;
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
public int Property1 {
get { return _property1; }
set { SetPropertyField("Property1", ref _property1, value); }
}
public string Property2 {
get { return _property2; }
set { SetPropertyField("Property2", ref _property2, value); }
}
public double Property3 {
get { return _property3; }
set { SetPropertyField("Property3", ref _property3, value); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
通常,我还将 OnPropertyChanged 方法设为虚拟方法,以允许子类覆盖它以捕获属性更改。
当属性更改时引发事件正是 INotifyPropertyChanged 所做的。 实现 INotifyPropertyChanged 需要一个成员,那就是 PropertyChanged 事件。 您自己实现的任何内容都可能与该实现相同,因此不使用它没有任何好处。
public event EventHandler ImageFullPath1Changed;
public string ImageFullPath1
{
get
{
// insert getter logic
}
set
{
// insert setter logic
// EDIT -- this example is not thread safe -- do not use in production code
if (ImageFullPath1Changed != null && value != _backingField)
ImageFullPath1Changed(this, new EventArgs(/*whatever*/);
}
}
也就是说,我完全同意瑞安。 这种情况正是 INotifyPropertyChanged 存在的原因。
如果您更改您的属性以使用支持字段(而不是自动属性),您可以执行以下操作:
public event EventHandler ImageFullPath1Changed;
private string _imageFullPath1 = string.Empty;
public string ImageFullPath1
{
get
{
return imageFullPath1 ;
}
set
{
if (_imageFullPath1 != value)
{
_imageFullPath1 = value;
EventHandler handler = ImageFullPathChanged;
if (handler != null)
handler(this, e);
}
}
}
已经有很好的答案了,但有些人还是一头雾水
class Program
{
static void Main(string[] args)
{
Location loc = new Location();
loc.LocationChanged += (obj, chngLoc) =>
{
Console.WriteLine("Your LocId Is");
Console.WriteLine(chngLoc.LocId);
Console.WriteLine(chngLoc.LocCode);
Console.WriteLine(chngLoc.LocName);
Console.ReadLine();
};
Console.WriteLine("Default Location Is");
Console.WriteLine(loc.LocId);
Console.WriteLine("Change Location");
loc.LocId = Console.ReadLine();
}
}
public class Location
{
private string _locId = "Default Location";
public string LocId
{
get
{
return _locId;
}
set
{
_locId = value;
if (LocationChanged != null && value != LocId)
{
B1Events b1 = new B1Events();
b1.LocCode = "Changed LocCode";
b1.LocId = value;
b1.LocName = "Changed LocName";
LocationChanged(this, b1);
}
}
}
public event EventHandler<B1Events> LocationChanged;
}
public class B1Events : EventArgs
{
public string LocId { get; set; }
public string LocCode{ get; set; }
public string LocName { get; set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.