2017-07-13 34 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