c# - 调用 Command.Execute 是错误的还是如何以更适合的方式重写

标签 c# xamarin

当我单击导致 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/

相关文章:

c# - LINQ 列表中按类型分组的项目总和列表

c# - 如何惰性地获取空组

c# - Xamarin 中的 SSL 握手失败

c# - System.DllNotFoundException :/system/lib/libsqlite. 所以

android - Xamarin In App Billing 插件无法连接

c# - Xamarin C# 一个 UITableView 中的两个 UITableViewCells

c# - BackgroundWorker 中仅更新了 2 个进度条中的 1 个

c# - 不使用凭据 C# 发送邮件

c# - 哪个 Windows IDE 可以编写、执行和调试单文件 C# 程序?

具有 2 个内容的 Android LinearLayout,一个应该占用 30dp,另一个应该占用其余的