INotifyPropertyChanged接口实现(appropriate event)和helper方法在我的代码中工作得很好,但我真的不明白它是如何工作的。在我看来,我的书没有很好地向我解释它,或者我不是很聪明。我们有一个单独的类Car.cs添加到我的解决方案中,代码如下(书中的示例),它应该在双向绑定中工作,因为当对象的示例也被更改时,我的WPF应用程序中的TextBox控件也被更改:
public class Car: INotifyPropertyChanged
{
private string _make;
private string _model;
public event PropertyChangedEventHandler PropertyChanged;
public Car()
{
}
public string Make
{
get { return _make; }
set
{
if (_make != value)
{
_make = value;
OnPropertyChanged("Make");
}
}
}
public string Model
{
get { return _model; }
set
{
if(_model != value)
{
_model = value;
OnPropertyChanged("Model");
}
}
}
private void OnPropertyChanged (string propertyName)
{
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}}
这里是我学习微软学习材料后自己做的代码,它看起来和工作更好海事组织:
public class Car: INotifyPropertyChanged
{
private string _make;
private string _model;
public event PropertyChangedEventHandler PropertyChanged;
public Car()
{
}
public string Make
{
get { return _make; }
set
{
_make = value;
OnPropertyChanged();
}
}
public string Model
{
get { return _model; }
set
{
_model = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged ()
{
if (PropertyChanged != null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
}
} }
所以我有一个愚蠢的问题,关于书中的例子(第一个):
1.这部分的意思是什么?如果属性不等于值,检查它的意义是什么(在属性的Set部分,你检查类的字段是否不等于值时,从来没有见过这样的情况)?即使没有它,代码也能工作。书中没有对它的解释。下面是有问题的代码:
如果您有一个值,那么您就可以设置一个值。OnPropertyChanged(“制造”);}
1.为什么如果你在上面提到的一小段代码(第一段)中写属性的名称时没有括号,那么它就不起作用呢?我的意思是如果你写Make,那么它就不起作用,你应该写“Make”。
提前感谢!
4条答案
按热度按时间rur96b6h1#
INotifyPropertyChanged是一个接口,它只需要一个类来实现它的需求。它基本上“只是”一个事件。
方法OnPropertyChanged只是引发此事件的“帮助程序”。但此处重要的部分是INotifyPropertyChanged实现本身不执行任何操作。
但是WinForms和WPF会自动在一些更高层次的类中订阅此类事件。它们通过反射来标识此类,并将自己添加到PropertyChanged事件的订阅者之一-您的类仍然需要引发该事件。
为此,您需要覆盖属性的Setter:
否则订阅者将永远不会得到通知。然而,这样做的全部目的是将更改的处理与“模型”分离,这样您的类就充当了数据的容器-因为容器可以传递给不同的窗体,窗体可能希望以不同的方式处理此容器。
检查值是否实际更改只是您可以做的事情-防止通知订阅者(比如说您的数据网格)重新运行您为此类属性设置的所有验证。为了避免不必要的此类验证运行,这将防止通知订阅者此类更改,其中值被重新分配,但它保持不变。
然而,订阅者的自动连接对于作为开发人员的您来说是抽象的,这可能会给初学者带来理解上的困难-然而,从长远来看,这会使您的生活更加容易,因为您可以依赖框架本身(较少用于实现、测试等),所以使用INotifyPropertyChange接口只是一个“约定”,但基本的构建块是通用的C#构造。
希望这能帮上一点忙:)
m0rkklqb2#
以下是如何正确实现IPropertyChanged接口的基本示例,该接口通知视图在属性值更改时重新绘制。
如果你想更进一步,并希望在你的属性改变时有一个操作,你可以这样做。
backingStore type T = private property
您可以为它指定一个在属性更改后执行的操作。
23c0lvtd3#
1.由于引发
PropertyChanged
事件可能会对性能造成很大影响(例如,当复杂视图必须重绘自身以显示最新数据时),因此建议仅在必要时引发该事件。只有当新值发生变化时才需要更新绑定。在新值和旧值相同时更新绑定是多余的,而且可能会导致开销增加。
下面的示例是一个非常详细的版本,用于突出显示正在发生的事情:
出于性能原因,将空字符串(
string.Empty
或""
)或null
(而不是属性名称)传递给PropertyChangedEventArgs
示例将指示绑定引擎更新引发PropertyChanged
事件的类的 * 所有 * 绑定。换句话说,这就像同时为所有属性引发
PropertyChanged
事件。这就是为什么只有在明确需要此行为时才执行此操作(例如,重置和清除所有属性时):
"Make"
被称为字符串文字。编译器将双引号中的每个文字解释为纯文本(字符串文字)。如果不是双引号,编译器将认为该值是语言对象(例如变量或类型)。如果您检查
PropertyChangedEventArgs
的建构函式签章,就会发现它预期属性名称为string
。使用
Make
(不带双引号)是一个简单的值引用(局部变量或成员变量),它返回Make
属性的 value,而不是属性(成员名称)的 name。需要属性名称来告诉绑定引擎哪个属性已更改,因此需要更新哪个
Binding
。下列范例假设属性
Make
设定为值"BMW"
:版本B)不起作用,因为绑定引擎需要属性的成员名称,而不是属性值。
请参阅Microsoft文档:字符串和字符串文字以了解字符串。
请参见
INotifyPropertyChanged
以了解实现该接口的推荐模式备注
使用
if
陈述式 * 和 * Null条件运算子?.
或?[]
检查null
的变数(例如事件委派)是多馀的。在高性能代码中,您可能希望避免冗余的双重检查。
以下版本相同:
58wvjzkj4#
如果属性不等于值,检查它有什么意义
它只是为了避免不必要的更新。2它并不是严格要求的。3每当你有事件通知某个东西被更新的时候,检查这个东西是否真的被改变了通常是一个好主意,因为你不知道什么在监听这个事件,它可能潜在地触发一些缓慢的计算。
为什么如果你在上面提到的一小段代码(在第一分段中)中写的属性名称没有括号,那么它就不能工作呢?
因为事件需要一个字符串,你可以让编译器为你插入这个字符串,方法是写
OnPropertyChanged(nameof(Make));
。你也可以使用CallerMemberName属性让编译器自动插入这个字符串,只要在你的属性中调用OnPropertyChanged()
。更进一步,您可以创建一个同时执行比较、字段更新和事件的方法,从而可以编写一行setter
=> Set(ref _make, value);
但是,我倾向于将所有这些都 Package 在一个单独的类中:
这样,您就可以声明一个类似
public Changeable<string> Make {get;} = new ("");
的属性,并像{Binding Make.Value}
那样绑定到它