通知viewmodel的所有属性已更改为null或字符串为空

时间:2017-03-27 14:22:02

标签: c# mvvm uwp inotifypropertychanged

我来自开发WPF解决方案,其中更新viewmodel的所有属性非常简单:

OnPropertyChanged(String.Empty);

在通用Windows平台方案中,我只有相同的方法来更新/刷新属性。这在大多数情况下都可以正常工作,但有时它会产生如下错误:

  

COMException错误HRESULT E_FAIL已从对COM组件的调用返回。在System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender,PropertyChangedEventArgs e)的GeooyTool.Base.BindableBase.OnPropertyChanged(String propertyName)at Pooo.set_Root(UserRoot value)at Booo.d__26.MoveNext()---堆栈跟踪结束从抛出异常的先前位置---在GeekyTool.Base.PageBase.d__1.MoveNext()的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)处---在抛出异常的前一个位置的堆栈跟踪结束---在System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()的System.Runtime.CompilerServices.AsyncMethodBuilderCore。<> c.b__6_0(对象状态)中/ p>

OnPropertyChanged接口实现的INotifyPropertyChanged方法如下所示:

public abstract class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public virtual bool Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if (object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

您可以浏览mvvm库,但INotifyPropertyChanged实现没有任何不同。

GeekyTool Library on Github

3 个答案:

答案 0 :(得分:2)

我在堆栈跟踪中看到有一些异步代码,因此我建议只使用OnPropertyChanged(String.Empty)调用Dispatcher,如下所示:

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    OnPropertyChanged(string.Empty);
});

答案 1 :(得分:2)

感谢所有的答案,我试图解决一个错误,它不存在。

在OnPropertyChanged(string.Empty)方法中引发错误,因为它之前的页面出现了同步上下文问题。

当您在两个页面之间非常快速地导航并且在OnNavigatedTo方法中有一些异步调用时,它们还没有完成。等待异步方法,但是在此页面中没有处理用户等到完成此操作后的页面。

只是要知道不需要应用@PedroLamas修复。在完成所有异步调用之前确保页面已完成。

答案 2 :(得分:1)

如果没有传递任何(或null)不相同的字符串,那么CallerMemeberName会调用成员名称。

我先解决这个问题。

public bool IsValid
{
    get { return isValid; }
    set
    {
        if (isValid == value)
        {
            return;
        }

        isValid = value;
        OnPropertyChanged();
    }
}

这应该有效。通常在我不能使用ReactiveObject或ObservableObject的地方,我倾向于使用它。