【发布时间】:2018-08-30 17:29:49
【问题描述】:
我有一个 MVVM WPF 应用程序。我有一个窗口,比方说“LvWindow”,它有一个从来自数据库的数据加载的列表视图。从主窗口“MainWindow”,我有一个菜单,其中有一些选项。当我选择访问“LvWindow”的选项时,它是打开的。然后从 ViewModel 中,在构造函数中调用一个数据库,从该数据库中请求一些数据,然后将这些数据加载到列表视图中。
我的目标是使进程从数据库中请求数据,然后将其异步加载到列表视图中。我希望这样做是为了不阻止整个应用程序,我的意思是,在加载此窗口期间,用户可以转到主窗口菜单并选择打开另一种类型的窗口。窗口在选项卡中打开。
在从数据库请求数据并加载到窗口“LvWindow”中的列表视图的过程中,我会在其上显示“正在加载”的飞溅(实际上这是一个将 zindex 设置为更高数字的矩形,以避免用户可以与 listview 交互,直到它完全加载)。当列表视图加载来自数据库的数据时,此启动画面将关闭。
因此,为了使流程异步,我知道在 winforms 中可以通过使用 beginInvoke、endInvoke 和回调方法使用委托来完成,请参阅 here。
另外,另一种可能性是使用后台工作人员,例如发布的here。
那么在 WPF 中哪一种是最好的方法呢?使用委托作为 winform 或后台工作人员?
尝试 #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(a) 行中抛出异常:
TargetParameterCountException: the parameter count mismatch
UserData 是我的数据模型,它是一个具有一些公共属性的类。比如:
public class UserData
{
public string ID{ get; set; }
public string Name { get; set; }
public string Surname { get; set; }
// Other properties
}
所以问题是对数据库的调用返回“RequestDataToDatabase”正在返回 UserData (ObservableCollection) 的集合,因此引发了异常。
不知道怎么解决。请问你能帮帮我吗?
最终解决方案:
正如 XAMIMAX 在 cmets 中所说:
- 将签名从 static void UIThread(Action a) 更改为 static void UIThread(Action a)
- 修改 UIThread((p) => LstUsers = 结果);通过 UIThread(() => LstUsers = 结果);
【问题讨论】:
-
你说的是 MvvM,但你从来没有提到过
ViewModel。如果这是 MvvM,尽管缺少视图模型,您可以使用Async Binding。 -
"...在其构造函数中,我调用了一个数据库",这不是 MVVM 方式。
-
@Filburt 抱歉,我的意思是,viewmodel 的构造函数。
-
将签名从
static void UIThread(Action<object> a)更改为static void UIThread(Action a)。这将允许方法按照它期望的参数执行。 -
@XAMlMAX 最好发布另一个问题,我将在那里详细解释。我会回来并在 cmets 中发布链接。
标签: c# wpf listview asynchronous delegates