在 wpf 和 mvvm 中使用后台计算实现用户界面命令
Implement user interface command with background computing in wpf & mvvm
我在执行用户界面命令时遇到一些困难。
我使用 wpf、棱镜和 mvvm。我的应用程序有两个区域 - 主区域和菜单。
当应用程序在菜单区域(NavBarControl、Devexpress)中加载时,注册菜单项 (NavBarGroup)。每个 NavBarGroup 都有一些 NavBarItem。当 NavBarItem 被 selected 时,绑定执行的命令。一些命令允许创建一个实体。但是对于那个应用程序来说,必须从服务器加载一些数据,此时用户界面应该是响应式的。我试图通过下一种方式实现该用途:
this.createAccount.Command = (ICommand)new DelegateCommand(this.ExecuteCreateAccount);
private void ExecuteCreateAccount()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, "show", null);
if (this.isCreateAccountProcessing)
{
return;
}
this.isCreateAccountProcessing = true;
Task.Factory.StartNew(() => this.AccountListViewModel.LoadUsersCollection()).GetAwaiter().OnCompleted(this.ShowAccountEditor);
}
private void ShowAccountEditor()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, null, null);
this.isCreateAccountProcessing = false;
if (this.createAccount.IsSelected)
{
this.AccountListViewModel.CreateNewItem();
}
}
但也许有更好的方法来实现这个目标?
当后台计算发生时,应用程序显示加载程序 (AppEvent.OnShowNotificationEvent)。如果用户 select 另一个菜单项,则该命令被视为已取消,不应显示帐户编辑器。
既然你使用的是DevExpress框架,我建议你使用AsyncCommand。根据文档,它是为您描述的场景设计的。
Prism 的 DelegateCommand
可以处理 async
任务。这个怎么样:
this.createAccount.Command = (ICommand)new DelegateCommand(this.ExecuteCreateAccount);
private async Task ExecuteCreateAccount()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, "show", null);
if (this.isCreateAccountProcessing)
{
return;
}
this.isCreateAccountProcessing = true;
await this.AccountListViewModel.LoadUsersCollection());
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, null, null);
this.isCreateAccountProcessing = false;
if (this.createAccount.IsSelected)
{
this.AccountListViewModel.CreateNewItem();
}
}
也就是说,如果AccountListViewModel.LoadUsersCollection()
可以异步。否则你应该把它包裹在 Task.Run
这样的
await Task.Run( () => this.AccountListViewModel.LoadUsersCollection() );
我在执行用户界面命令时遇到一些困难。 我使用 wpf、棱镜和 mvvm。我的应用程序有两个区域 - 主区域和菜单。 当应用程序在菜单区域(NavBarControl、Devexpress)中加载时,注册菜单项 (NavBarGroup)。每个 NavBarGroup 都有一些 NavBarItem。当 NavBarItem 被 selected 时,绑定执行的命令。一些命令允许创建一个实体。但是对于那个应用程序来说,必须从服务器加载一些数据,此时用户界面应该是响应式的。我试图通过下一种方式实现该用途:
this.createAccount.Command = (ICommand)new DelegateCommand(this.ExecuteCreateAccount);
private void ExecuteCreateAccount()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, "show", null);
if (this.isCreateAccountProcessing)
{
return;
}
this.isCreateAccountProcessing = true;
Task.Factory.StartNew(() => this.AccountListViewModel.LoadUsersCollection()).GetAwaiter().OnCompleted(this.ShowAccountEditor);
}
private void ShowAccountEditor()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, null, null);
this.isCreateAccountProcessing = false;
if (this.createAccount.IsSelected)
{
this.AccountListViewModel.CreateNewItem();
}
}
但也许有更好的方法来实现这个目标? 当后台计算发生时,应用程序显示加载程序 (AppEvent.OnShowNotificationEvent)。如果用户 select 另一个菜单项,则该命令被视为已取消,不应显示帐户编辑器。
既然你使用的是DevExpress框架,我建议你使用AsyncCommand。根据文档,它是为您描述的场景设计的。
Prism 的 DelegateCommand
可以处理 async
任务。这个怎么样:
this.createAccount.Command = (ICommand)new DelegateCommand(this.ExecuteCreateAccount);
private async Task ExecuteCreateAccount()
{
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, "show", null);
if (this.isCreateAccountProcessing)
{
return;
}
this.isCreateAccountProcessing = true;
await this.AccountListViewModel.LoadUsersCollection());
AppEvent.OnShowNotificationEvent(UTNotificationType.ChangeMainLoaderStatus, null, null);
this.isCreateAccountProcessing = false;
if (this.createAccount.IsSelected)
{
this.AccountListViewModel.CreateNewItem();
}
}
也就是说,如果AccountListViewModel.LoadUsersCollection()
可以异步。否则你应该把它包裹在 Task.Run
这样的
await Task.Run( () => this.AccountListViewModel.LoadUsersCollection() );