当我单击导致 LoginCommand
触发的登录按钮时,我正在执行一些长时间运行的任务。
我还通过调用 LoginCommand.Execute()
在我的 ViewModel 的 OnAppearing
中调用此 LoginCommand
。我想最好调用一些函数来完成这个。有没有更清洁的好方法?
这是我的 LoginViewModel
派生自 BaseViewModel
的内容。我的 BasePage
调用 OnAppearing
public class BaseViewModel : INotifyPropertyChanged
{
public virtual void OnAppearing() { }
}
public class LoginViewModel: BaseViewModel
{
public override void OnAppearing() {
// is there a better way than calling the LoginCommand itself?
LoginCommand.Execute(this);
}
public ICommand LoginCommand
{
get
{
return new Command(async () =>
{
var validationResult = await SomeLongRunningValidation();
if (!validationResult.Authenticated)
{
await navigation.DisplayAlert("Error", "Authentication failed. Try again?", "Yes", "No");
}
});
}
}
}
最佳答案
评论中的建议是准确的。
首先提取命令处理程序中的代码并将其封装到它自己的异步方法中。让命令处理程序在调用时调用它。提取的方法也可以从其他方法调用,例如 OnAppearing
。为避免阻塞,您希望保持代码异步。您可以创建一个异步事件处理程序来处理在引发事件时调用异步方法。
public class LoginViewModel: BaseViewModel {
private event EventHandler Appearing = delegate { };
public override void OnAppearing() {
EventHandler handler = null;
handler = async (sender, e) => {
Appearing -= handler; //Unsubscribe from event
await LoginAsync(); // non-blocking async call
};
Appearing += handler;//Subscribe to event
Appearing(this, EventArgs.Empty);//raise event
}
private ICommand loginCommand = new Command(async () => {
await LoginAsync();//non-blocking async call
});
public ICommand LoginCommand {
get {
return loginCommand;
}
}
private async Task LoginAsync() {
var validationResult = await SomeLongRunningValidation();
if (!validationResult.Authenticated) {
await navigation.DisplayAlert("Error", "Authentication failed. Try again?", "Yes", "No");
}
}
}
没有代表的版本
public class LoginViewModel: BaseViewModel {
public LoginViewModel() : base() {
Appearing += handler;//Subscribe to event
}
private event EventHandler Appearing = delegate { };
private async void handler(object sender, EventArgs e) {
Appearing -= handler; //Unsubscribe from event
await LoginAsync(); // non-blocking async call
}
public override void OnAppearing() {
Appearing(this, EventArgs.Empty);//raise event
}
private ICommand loginCommand = new Command(async () => {
await LoginAsync();//non-blocking async call
});
public ICommand LoginCommand {
get {
return loginCommand;
}
}
private async Task LoginAsync() {
var validationResult = await SomeLongRunningValidation();
if (!validationResult.Authenticated) {
await navigation.DisplayAlert("Error", "Authentication failed. Try again?", "Yes", "No");
}
}
}
关于c# - 调用 Command.Execute 是错误的还是如何以更适合的方式重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47205424/