使用 MVVM 模式在 UserControl WPF 中异步加载

Loading asynchronously in a UserControl WPF with MVVM pattern

我在使用 WPF MVVM 模式的视图中遇到异步加载程序的小问题。 我希望当我单击按钮 Read from UserControl View 时,发送一个 Command 到 view model ,然后它在执行之前停止加载,当我 return data 时它消失了。 数据由机器通过光学 USB 读取。 一切正常,程序运行完美,只是无法调出如此异步的加载。加载与阅读的 return 一起显示,因为同步 .我该怎么做异步?我在任务中尝试过,但他似乎不考虑代码。

class  ReadAndPrintFromDevice : ICommand
    {
        async Task<int> showLoader()
        {
           model.ShowLoader = true;                         
           return 1;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {                    
            return true;
        }

        public async void Execute(object parameter)
        {
            showLoader async here
            //other code..
            showloader async shadow here, after other code
        }
    }

如果您需要更多信息,请在评论中告诉我,我将全部添加。

我建议这样:

public class ReadAndPrintFromDeviceAsyncCommand : PropertyChangedBase, ICommand
{
    private bool _IsBusy;

    public bool IsBusy
    {
        get { return _IsBusy; }
        private set
        {
            _IsBusy = value;
            NotifyOfPropertyChange();
        }
    }

    public bool CanExecute(object parameter)
    {
        return !IsBusy;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public async void Execute(object parameter)
    {
        IsBusy = true;

        await ...

        IsBusy = false;
    }
}

通过使用 IsBusy 属性,您可以在执行异步操作之前简单地将其设置为 true,一旦完成,将其设置回 false。

然后您可以将控件绑定到 IsBusy 属性:

<MyControl Visibility="{Binding SomeCommand.IsBusy, ...}"

上面的例子需要 BooleanToVisibilityConverter 才能工作,但我想你明白了。

此外,该命令使用我创建的 PropertyChangedBase 来简单地使实施 INotifyPropertyChanged 更容易一些,此 class 的代码在这里:

public abstract class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyOfPropertyChange([CallerMemberName]string propertyName = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}