【发布时间】:2017-05-21 13:28:18
【问题描述】:
在属性的设置器中,有时我必须将属性的值更改为当前设置的值以外的值。无论如何,这对于 Windows 应用商店应用程序而言,仅通过引发 PropertyChanged 事件是行不通的。我可以更改该值,但 UI 不会根据该更改自行更新。
<TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
视图模型:
class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string text;
public string Text
{
get { return text; }
set
{
if ( text != value ) {
text = value == "0" ? "" : value;
OnPropertyChanged();
}
}
}
protected void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
我写了以下方法很好地解决了这个问题:
protected void OnPropertyChanged_Delayed( [CallerMemberName] string propertyName = null )
{
Task.Delay( 1 ).ContinueWith(
t => OnPropertyChanged( propertyName ),
TaskScheduler.FromCurrentSynchronizationContext()
);
}
我用这个来代替OnPropertyChanged。但我最近在我的 Windows 应用商店应用程序中发现了一个间歇性错误,这是由用户离开页面后发生的 OnPropertyChanged_Delayed 调用引起的。这导致我寻求替代解决方案。
有没有更好的方法来从其设置器中更改属性的值并将更改通知 UI?我目前正在开发一个 Windows 应用商店应用程序,所以我想在这种情况下得到答案。但我最终会将它移植到 UWP。这也是UWP的问题吗?如果是这样,我也想要一个解决方案(可能相同)。
【问题讨论】:
-
所以我假设您的视图模型触发了事件,您的屏幕捕获了该事件,但该屏幕已被导航离开?
-
@CodingYoshi 是的,在这种情况下,视图模型会从属性的设置器中触发事件。
-
我的意思是你为什么需要
OnPropertyChanged_Delayed?这是代码气味。如果您想通知属性已更改,则只需通知即可。为什么要推迟? -
@HappyNomad 虽然您说“有时我必须将属性值更改为当前设置的值以外的值”,但您没有解释为什么应该延迟触发 PropertyChanged 事件。 Mark给出的答案显示了如何同步进行。
-
所以你在设置你的属性时有一个竞争条件?是否有另一个控件试图更改属性但您也想更改它?当您更改值时,您应该阻止该控制器的事件处理程序。我能给出的最便宜的方法是使用布尔辅助值来检查是否必须通知属性。 (问题的根源是,当你不想要它时,你不应该首先设置属性。)
标签: c# xaml windows-store-apps uwp inotifypropertychanged