英文:
subscribe a read only property to the PropertyChanged event mvvm
问题
在视图模型中,有一个属性依赖于另一个属性的值:
private int _property;
public int Property
{
get
{
return _property;
}
set
{
SetProperty(ref _property, value, () => Property);
}
}
public int DependentProperty => Property + SomeLogic;
以及视图:
<TextBlock Text="{Binding DependentProperty}" />
当 _property
更改时,我希望更新视图。
我找到了这个问题,它说你需要订阅 Property
的 PropertyChanged
事件,但我不知道如何做。
英文:
In the view model there is a property that is dependent to another property value:
private int _property;
public int Property
{
get
{
return _property;
}
set
{
SetProperty(ref _property, value, () => Property);
}
}
public int DependentProperty => Property + SomeLogic;
and the view:
<TextBlock Text="{Binding DependentProperty}" />
I want to update the view when the _property changes
I found :this question
that says you have to subscribe to the PropertyChanged event of Property, but I don't know how.
答案1
得分: 1
DependentProperty
被称为计算属性。在您的情况下,通过调用 SetProperty
方法隐式触发了 INotifyPropertyChanged.PropertyChanged
事件。您所需做的就是显式为计算属性触发事件。
通常,您可能已经有一个事件激发方法的实现,该方法也在 SetProperty
方法内部使用。
例如,如果您使用 .NET Community Toolkit,您已经继承了一个 protected virtual ObservableObject.OnPropertyChanged(propertyName: string): void
方法,您可以调用该方法。
private int _property;
public int Property
{
get => _property;
set
{
// 隐式为此属性触发 PropertyChanged 事件
// 因为 SetProperty 内部调用了 OnPropertyChanged(事件激发方法)。
SetProperty(ref _property, value, () => Property);
// 显式为计算属性触发 PropertyChanged 事件
OnPropertyChanged(nameof(DependentProperty));
}
}
public int DependentProperty => Property + SomeLogic;
当然,如果您希望避免从每个计算属性依赖的每个属性显式触发 PropertyChanged
事件,您可以观察所需的属性以进行更改:
private int _property;
public int Property
{
get => _property;
set => SetProperty(ref _property, value, () => Property);
}
public int DependentProperty => Property + SomeLogic;
public ViewModel()
{
TrackDependentPropertySourceProperties();
}
private void TrackDependentPropertySourceProperties()
{
this.PropertyChanged += OnDependentPropertySourcePropertiesChanged;
}
// 假设 DependentProperty 依赖于另外三个属性
// (使用三个来突出显示这种模式)
private void OnDependentPropertySourcePropertiesChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(Property):
case nameof(SomeOtherProperty):
case nameof(AThirdProperty):
OnPropertyChanged(nameof(DependentProperty));
}
}
英文:
The DependentProperty
is called computed property. In your case the INotifyPropertyChanged.PropertyChanged
event is raised implicitly by calling the SetProperty
method. All you have to do is to raise the event for the computed property explicitly.
Usually you already have an event invocator method implementation that is also used internally by the SetProperty
method.
For example, if you use the .NET Community Toolkit you already inherit a protected virtual ObservableObject.OnPropertyChanged(propertyName: string):void
method that you can call.
private int _property;
public int Property
{
get => _property;
set
{
// Implicitly raises the PropertyChanged event for this property
// because SetProperty is calling OnPropertyChanged (event invocator method) internally.
SetProperty(ref _property, value, () => Property);
// Raise the PropertyChanged event explicitly for the computed property
OnPropertyChanged(nameof(DependentProperty));
}
}
public int DependentProperty => Property + SomeLogic;
Of course, if you want to avoid the explicit raising of the PropertyChanged
event from every property that the computed property depends on, you can observe the required properties for changes:
private int _property;
public int Property
{
get => _property;
set => SetProperty(ref _property, value, () => Property);
}
public int DependentProperty => Property + SomeLogic;
public ViewModel()
{
TrackDependentPropertySourceProperties();
}
private void TrackDependentPropertySourceProperties()
{
this.PropertyChanged += OnDependentPropertySourcePropertiesChanged;
}
// Assume that DependentProperty depends on three other properties
// (use three to highlight the pattern)
private void OnDependentPropertySourcePropertiesChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(Property):
case nameof(SomeOtherProperty):
case nameof(AThirdProperty):
OnPropertyChanged(nameof(DependentProperty));
}
}
答案2
得分: 0
你需要实现INotifyPropertyChanged
接口到模型中。
然后实现:
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
当你设置属性时,只需调用OnPropertyChanged(<属性名称>)
。
建议:不要将业务逻辑放在模型本身中。
英文:
you need to implement INotifyPropertyChanged
interface to model.
then implement
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
and when you set
the property just call OnPropertyChanged(<ProperyName>)
.
Suggestion: Do not put business logic into the model itself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论