在WPF中从ViewModel进行异步UI更新 [英] asynchronous UI update from ViewModel in WPF

查看:1218
本文介绍了在WPF中从ViewModel进行异步UI更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在从db获取数据并异步显示在UI中遇到问题. 我使用的是MVVM灯,当我单击按钮时,在ViewModel中触发了动作:

I am having a problem with getting data from db and showing in UI asynchronously. I am using MVVM light, when I click the button, action is triggered in ViewModel:

    private void SearchQuery(string query)
    {
        _redisModel.GetFriendsListAsync(query);
    } 

在某个时候,后台线程会调用GetFriendsListCompleted,通知viewmodel工作已完成. 此时,我需要更新ListBox ItemSource.但是当我尝试更新时 调用线程无法访问该对象,因为其他线程拥有它" 我尝试了 Dispatcher.CurrentDispatcher.Invoke(),App.Current.Dispatcher.Invoke()和其他魔术,但仍然无法正常工作.

At some point GetFriendsListCompleted is called by background thread notifing viewmodel that job is done. At this point I need to update ListBox ItemSource. But when I try to update is I get "The calling thread cannot access this object because a different thread owns it" I have tried Dispatcher.CurrentDispatcher.Invoke(),App.Current.Dispatcher.Invoke() and different magic, but it still doesn’t work.

我试图将UI调度程序提供给ViewModel,然后从那里调用它-无效.

I tried to give UI dispatcher to ViewModel and then call it from there - didn't work.

private string filterText = string.Empty;
    public string FilterText
    {
        get { return filterText; }
        set
        {
            filterText = value;
            this.RaisePropertyChanged(() => this.FilterText);

            this.FriendsList.View.Refresh(); // Here where exception is happening.
        }
    }

我试图将这一行更改为

Dispatcher.Invoke(DispatcherPriority.Normal,new Action( ()=> this.FriendsList.View.Refresh())); -还是一样.

Dispatcher.Invoke(DispatcherPriority.Normal, new Action( () =>this.FriendsList.View.Refresh())); - still the same.

我正在使用Telerik ListBox显示项目. FriendList是CollectionViewSource( http://www.telerik.com/help/wpf/radlistbox -overview.html ).当我使用WPF控件示例中的Telerik示例时,它可以工作.当我使用异步方法时,开始出现问题. 视图类型为System.ComponentModel.ICollectionView,用于过滤和分组.

I am using Telerik ListBox to display items. FriendList is CollectionViewSource(http://www.telerik.com/help/wpf/radlistbox-overview.html). It works when I use Telerik example from WPF Control Examples. Problems start to occur when I use my async methods. Type of view is System.ComponentModel.ICollectionView it is used for Filtering and Grouping.

我也试图将ObservableCollection分配给ListBox的Items属性,它也不起作用.

I have also tried to just assign ObservableCollection to Items property of the ListBox and it doesn't work either.

有关_redisModel.GetFriendsListAsync如何工作的更多详细信息: 最后(在所有通话链之后)最终在这里结束:

A bit more details on how _redisModel.GetFriendsListAsync works: In the end(after all chain of calls) it ends up here:

public GetAsyncResult(Func<T> workToBeDone, Action<IAsyncResult> cbMethod, Object state)
{
   _cbMethod = cbMethod;
   _state = state;
   QueueWorkOnThreadPool(workToBeDone);
}

ThreadPool.QueueUserWorkItem(state =>
{
  try
  {
     _result = workToBeDone();
  }
  catch (Exception ex)
  {
       _exception = ex;
  }
  finally
  {
     UpdateStatusToComplete(); //1 and 2 
     NotifyCallbackWhenAvailable(); //3 callback invocation 
  }
 });

在viewmodel中,我有方法:

In viewmodel I have method:

private void GetFriendsListCompleted(object sender, ResultsArgs<Friend> e)
    {
        if (!e.HasError)
        {
            var curr = e.Results;
            if (curr != null)
            {
                this.FriendsList= new CollectionViewSource();

                this.FriendsList.Source = list;
                this.FriendsList.Filter += this.FriendFilter;
                FilterText = "";

                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(

                        () => this.FriendsList.View.Refresh()));
            }
    }

有人可以帮我吗? 谢谢

Can anybody please help me with this ? Thank you

推荐答案

您正在一个线程中创建CollectionViewSource,并在另一个线程(调度程序线程)中对其进行刷新.将您的GetFriendsListCompleted更新为

You are creating CollectionViewSource in one thread and refreshing that in another thread (dispatcher thread). Update your GetFriendsListCompleted to

private void GetFriendsListCompleted(object sender, ResultsArgs<Friend> e)
{
    if (!e.HasError)
    {
        var curr = e.Results;
        if (curr != null)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                    () => {
                     this.FriendsList= new CollectionViewSource();
                     this.FriendsList.Source = list;
                     this.FriendsList.Filter += this.FriendFilter;
                     FilterText = "";
                     this.FriendsList.View.Refresh();
                     }));
        }
    }
}

这篇关于在WPF中从ViewModel进行异步UI更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆