使用 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));
}
}
我在使用 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));
}
}