2017-07-13 29 views
1

我有一个MVVM WPF应用程序。我有一个窗口,让我们说“LvWindow”,它具有从数据库来的数据加载的列表视图。从主窗口“MainWindow”,我有一个菜单,它有一些选项。当我选择访问“LvWindow”的选项时,它是开放的。然后从ViewModel,在构造函数中,我调用了一个数据库,从中请求一些数据,然后加载到列表视图中。WPF:在.NET 3.5中异步执行一些代码

我的目标是让进程从数据库请求数据,然后在异步列表视图中加载它。我想这是为了不阻止整个应用程序,我的意思是,在这个窗口被加载期间,用户可以进入主窗口菜单并选择打开另一种窗口。 Windows在标签中打开。

虽然从数据库请求数据并在窗口“LvWindow”中将其加载到列表视图中的过程中,我会在其上显示一个名为“加载”的冒泡(实际上,这是一个zindex设置为较大数字以避免用户的矩形可以与listview交互,直到完全加载)。当列表视图与来自数据库的数据一起加载时,此飞溅将被关闭。

所以为了使进程异步,我知道在winforms中可以通过使用beginInvoke,endInvoke和回调方法来完成委托,参见here

此外,另一种可能性是使用后台工作者,如发布here

那么在WPF中最好的办法呢?使用代表作为winforms或后台工作人员?

未遂#1: 我试图XANIMAX的解决方案,因为这:

public class TestViewModel : BaseViewModel 
{ 
    private static Dispatcher _dispatcher; 
    public ObservableCollection<UserData> lstUsers 

    public ObservableCollection<UserData> LstUsers 
    { 
     get 
     { 
      return this.lstUsers; 
     } 

     private set 
     { 
      this.lstUsers= value; 
      OnPropertyChanged("LstUsers"); 
     } 
    } 

    public TestViewModel() 
    { 
     ThreadPool.QueueUserWorkItem(new WaitCallback((o) => 
     { 
      var result = getDataFromDatabase(); 
      UIThread((p) => LstUsers = result); 
     })); 
    } 

    ObservableCollection<UserData> getDataFromDatabase() 
    {    
     return this.RequestDataToDatabase(); 
    } 

    static void UIThread(Action<object> a) 
    { 
     if(_dispatcher == null) _dispatcher = Dispatcher.CurrentDispatcher; 
     //this is to make sure that the event is raised on the correct Thread 
     _dispatcher.Invoke(a); <---- HERE EXCEPTION IS THROWN 
    } 
} 

但线_dispatcher.Invoke(一)抛出一个异常:

的UserData是我的数据模型,它是一个具有一些公共属性的类。喜欢的东西:

public class UserData 
{ 
    public string ID{ get; set; } 
    public string Name { get; set; } 
    public string Surname { get; set; } 

    // Other properties 
} 

所以问题是,调用数据库返回“RequestDataToDatabase”正在恢复的UserData(的ObservableCollection)的集合,所以异常被抛出。

我不知道如何解决它。请问你能帮帮我吗?

最终的解决方案

  • 变化从静态无效UIThread(Action a)该签名以静态无效UIThread(行动一)
  • 修改UIThread:

    由于XAMIMAX在评论中说: ((p)=> LstUsers = result);通过UIThread(()=> LstUsers = result);

+3

你说MVVM却一次也没有让你提到一个'ViewModel'。如果这是MvvM,尽管缺少视图模型,您可以使用['Async Binding'](https://msdn.microsoft.com/en-gb/magazine/dn605875.aspx)。 – XAMlMAX

+4

*“...在其构造函数中我调用了数据库”*这不是MVVM方式。 – Filburt

+0

@Filburt对不起,我的意思是,viewmodel的构造函数。 – user1624552

回答

1

这是您可能的解决方案之一。
在您的视图模型,你会是这样的:

using System; 
using System.Collections.Generic; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Threading; 

namespace VM 
{ 
    public class TestViewModel : BaseViewModel 
    { 
     private static Dispatcher _dispatcher; 
     List<object> ListToDisplay { get; set; }//INPC omitted for brevity 
     public TestViewModel() 
     { 
      ThreadPool.QueueUserWorkItem(new WaitCallback((o) => 
      { 
       var result = getDataFromDatabase(); 
       UIThread((p) => ListToDisplay = result); 
      })); 
     } 

     List<object> getDataFromDatabase() 
     { 
      //your logic here 
      return new List<object>(); 
     } 

     static void UIThread(Action<object> a) 
     { 
      if(_dispatcher == null) _dispatcher = Dispatcher.CurrentDispatcher; 
      //this is to make sure that the event is raised on the correct Thread 
      _dispatcher.Invoke(a); 
     } 
    } 
} 
+0

我已经实现了你的解决方案,但我得到一个异常:TargetParameterCountException:参数计数不匹配。查看我的帖子更新。问题是从数据库返回信息的方法返回一组UserData。你能告诉我如何解决这个问题? – user1624552

1

正如你不能等待在构造函数中异步方法C#7.0(但异步主要在7.1推出)可以提取您的异步函数调用ViewModel中的单独函数,并在创建ViewModel并将其分配给View的DataContext后,在View的代码隐藏构造函数中同步调用此函数:

public MainWindow() 
{ 
    this.vm = new MyViewModel(); 
    this.DataContext = this.vm; 
    this.InitializeComponent(); 
    this.vm.AsychronousFunctionToCallDatabase(); 
} 

正如XAMIMAX所说,您希望实现ViewModel来处理视图和模型之间的业务逻辑。然后,如果您的ViewModel实现INotifyPropertyChanged,并且您将XAML中的Binding设置为ViewModel中的属性 - 则数据库调用后显示将刷新而不会阻塞UI线程。请注意,如果您从数据库调用填充了任何集合,那么它们应该是ObservableCollection类型。

但是正如Kundan所说,在AsychronousFunctionToCallDatabase()函数中,您应该在调用数据库的行中包含一个await语句或创建一个Task - 这会将控制权返回给调用函数(在本例中为MainWindow构造函数)。

+0

在网络3.5中有不支持任务。 – user1624552