异步方法导致奇怪的异常

时间:2013-09-08 14:20:21

标签: c# wpf data-binding mvvm async-await

我有一个绑定到ViewModel的WPF DataGrid,一切都很棒。我现在意识到我需要在DataGrid中加载比预期更多的数据。所以我使用async将该数据加载到Viewmodel容器非UI阻塞中。所以,在我的ResourceDataViewModel : ViewModelBase我有以下方法

public async void LoadResourceFilesAsync(string fullFileName = null)
{
    if (!String.IsNullOrEmpty(fullFileName))
        this.FullFileName = fullFileName;
    strategy = manager.InitialiseStrategy(this);
    if (strategy == null)
        return;

    ...

    // Get data asynchoniously.
    List<ResourceViewModel> resourceViewModelList = await strategy.LoadResourceFilesAsync();
    this.Resources = new TypedListObservableCollection<ResourceViewModel>(resourceViewModelList);

    // Setup event handlers.
    this.Resources.CollectionChanged += this.OnCollectionChanged;
    foreach (ResourceViewModel rvm in resourceViewModelList)
        rvm.PropertyChanged += this.OnResourceViewModelPropertyChanged;

    // Set the file name for View and ViewModel.
    this.FullFileName = strategy.FullFileName;
    base.DisplayName = Path.GetFileName(this.FullFileName); 

    ...
}

所以,在我制作加载方法async之前,一切都很顺利;加载了数据并且绑定到DisplayName标头属性的abstractViewModelBase TabItem类中定义的属性)导致文件名显示在{ {1}}标题正确。现在我已经使负载异步,数据加载到TabItem正如您在上面的代码中所期望的那样,但是,

DataGrid

不会更新base.DisplayName = Path.GetFileName(this.FullFileName); 而不是静默(即不在我的代码中抛出和执行)会导致base.DisplayName显示消息:

  

Message =“无法在对象实例上找到该方法。”

现在,我已将System.ArgumentException更改为base.DisplayName,这会停止异常,但仍然不会更新**this**.DisplayName TabItem为什么会发生这种情况,我该如何解决?

注意。我已经检查了正在执行它的线程,它是预期的MainThread / UIThread,这使得它非常异常。

更新。当我使用Header并且绑定显示this.DisplayName时(我找到了related question at MSDN),我已经使用Snoop来了解绑定所发生的事情。然而,我仍然对这里发生的事情感到茫然...


编辑地址评论

我的应用程序MainWindow {DisconnectedItem}DataContext;这包含一个属性

MainWindowViewModel

包含我想在每个public ObservableCollection<WorkspaceViewModel> Workspaces { ... } 中显示的ViewModel。我有另一个ViewModel(称为ResourceDataViewModel TabItem DataGrid ) which holds the public WorkspaceViewModel`,定义为

s and inherits from

并处理所有MVVM内容,例如public abstract class WorkspaceViewModel : ViewModelBase { ... } 处理程序等。在OnPropertyChanged中,将资源文件加载到主窗口中MainWindowViewModel的调用层次结构为:

TabControl

并且在public void LoadResourceFiles(string fullFileName = null) { // Build and load the ViewModel in to the View. ResourceDataViewModel workspace = new ResourceDataViewModel(this); workspace.LoadResourceFilesAsync(fullFileName); ... } 我有上面原始问题中显示的方法。然后,它从策略工厂获取策略并加载数据异步 - 在这种情况下使用以下方法

ResourceDataViewModel

注意,从这些方法返回的数据很好。 这些方法本身似乎不会导致上述问题 - 但是上下文切换可能是。我在这里真的很失落,所以任何想法都是最受欢迎的。

2 个答案:

答案 0 :(得分:0)

您是否尝试在用户界面中的相关IsAsync对象上将Binding类的True属性设置为Binding?这为我解决了类似的问题。

答案 1 :(得分:0)

我找到了解决这个问题的方法,但我不相信这是最好的方法,而且更像是一种解决方法。在ViewModel中我试图使用

base.DisplayName = "XYZ";

这不起作用。在上面交换this base可以防止异常,但我仍然有异常(WPF library bug我认为是这个问题的原因)。现在,要尝试解决DataContext切换问题,我已覆盖DisplayName中的ViewModelBaseResourceDataViewModel中的public override string DisplayName { get { return base.DisplayName; } protected set { if (base.DisplayName == value) return; base.DisplayName = value; OnPropertyChanged("DisplayName"); } }

DisplayName

这似乎可以解决绑定问题,但会稍微延迟TabItem {{1}}的显示。

我欢迎任何人拥有的任何其他解决方案,并希望这有助于其他人。