【问题标题】:Notifying all properties of the viewmodel has changed with null or string empty通知视图模型的所有属性已更改为 null 或字符串为空
【发布时间】:2017-08-20 07:33:25
【问题描述】:

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

OnPropertyChanged(String.Empty);

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

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

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

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

【问题讨论】:

  • 我很惊讶这是否曾经在 UWP 上工作过。处理String.Empty 属性名称的代码没有什么特别之处。你有完整的复制品吗? stackoverflow.com/help/mcve
  • @MattLacey,使用 string.empty 引发 INotifyPropertyChanged.PropertyChanged 事件是 AFAIK 的“旧”技巧,它在 UWP 中可以正常工作以强制所有(经典或编译的)绑定刷新!
  • 如果您使用 x:bind,您可以从页面后面的代码中调用 'this.Bindings.Update()' 来强制更新该页面上的所有绑定。

标签: c# mvvm uwp inotifypropertychanged


【解决方案1】:

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

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

【讨论】:

  • 问题是 OnPropertyChanged(string.Empty);是在一个设置器中完成的,所以我可以做的是一个异步操作而不等待它。那是对的吗?谢谢!
  • 正确,您无需等待Dispatcher 调用,您需要什么都没关系!
【解决方案2】:

CallerMemeberName 如果你没有传入任何不是同一个 string.empty 的内容(或 null),则拉取调用成员名称。empty

我会先解决这个问题。

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

        isValid = value;
        OnPropertyChanged();
    }
}

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

【讨论】:

  • 是的,但正如@PedroLamas 所说,使用string.Empty 引发INotifyPropertyChanged.PropertyChanged 事件是强制所有绑定更新/刷新的“旧”技巧。这就是我正在做的,一次更新。
【解决方案3】:

感谢所有答案,我正在尝试修复它不存在的错误。

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

当您在两个页面之间快速导航并且在 OnNavigatedTo 方法中有一些异步调用尚未完成时,就会发生这种情况。等待异步方法,但在此页面中未处理用户等待完成。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 2014-10-06
    • 1970-01-01
    • 2020-08-25
    相关资源
    最近更新 更多