WPF异步MVVM等待窗体
需求描述
在ViewModel 中处理Model 中的数据需要一定时间的等待;
ViewModel 或Model 在获取数据或访问同步服务时有一定延迟需要等待;ViewModel 操作View 加载数据需要一段时间;
解决办法
显示一个等待UI,当数据处理完毕或服务接口返回后等待UI消失
转动齿轮控件
参考开源实现SprocketControl :https://www.wendangku.net/doc/777189843.html,/
等待控件
复制代码
1
2 3 Grid.Column="0" 4 Width="100" 5 Height="100" 6 Margin="0,0,0,0" 7 HorizontalAlignment="Center" 8 VerticalAlignment="Center" 9 Background="Transparent" 10 Interval="60" 11 IsIndeterminate="True" 12 StartAngle="-90" 13 TickColor="{DynamicResource MaskForegroundColor}" 14 TickCount="16" 15 TickWidth="5" /> 16 复制代码 等待效果 定义MVVM 中的ViewModel 的状态 复制代码 /// /// 在MVVM模式中ViewModel的状态 /// [Flags] public enum ViewModelStatus { /// /// ViewModel无状态 /// None = 0x0, /// /// ViewModel正在初始化 /// Initializing = 0x1, /// /// ViewModel初始化完毕 /// Initialized = 0x2, /// /// ViewModel正在加载 /// Loading = 0x4, /// /// ViewModel加载完毕 /// Loaded = 0x8, /// /// ViewModel正在保存 /// Saving = 0x16, /// /// ViewModel保存完毕 /// Saved = 0x32 } 复制代码 ViewModel 状态转变为控件状态 复制代码 1 public class StatusToAnimationVisibilityConverter : IValueConverter 2 { 3 #region IValueConverter Members 4 5 public object Convert( 6 object value, Type targetType, object parameter, CultureInfo culture) 7 { 8 try 9 { 10 string status = value.ToString(); 11 12 switch (status) 13 { 14 case "Initializing": 15 case "Loading": 16 case "Saving": 17 return Visibility.Visible; 18 case "Loaded": 19 case "Saved": 20 default: 21 return Visibility.Collapsed; 22 } 23 } 24 catch (Exception) 25 { 26 return Visibility.Collapsed; 27 } 28 } 29 30 public object ConvertBack( 31 object value, Type targetType, object parameter, CultureInfo culture) 32 { 33 return DependencyProperty.UnsetValue; 34 } 35 36 #endregion 37 } 复制代码 使UserControl 支持异步显示 复制代码 1 x:Key="StatusToAnimationVisibilityConverter" /> 2 3 4 5 6 7 8 9 10 Width="Auto" 11 Height="Auto" 12 HorizontalAlignment="Stretch" 13 VerticalAlignment="Stretch" 14 Panel.ZIndex="2000" 15 Visibility="{Binding Path=Status, 16 Converter={StaticResource StatusToAnimationVisibilityConverter}}"> 17 18 Height="Auto" 19 HorizontalAlignment="Stretch" 20 VerticalAlignment="Stretch" 21 Panel.ZIndex="0" 22 Background="{DynamicResource MaskGridBackgroundBrush}" 23 Opacity="0.2" /> 24 25 26 27 28 29 30 复制代码 应用Style 至UserControl 复制代码 1 2 xmlns="https://www.wendangku.net/doc/777189843.html,/winfx/2006/xaml/presentation" 3 xmlns:x="https://www.wendangku.net/doc/777189843.html,/winfx/2006/xaml" 4 xmlns:d="https://www.wendangku.net/doc/777189843.html,/expression/blend/2008" 5 xmlns:mc="https://www.wendangku.net/doc/777189843.html,/markup-compatibility/2006" 6 d:DesignHeight="318" 7 d:DesignWidth="632" 8 Style="{DynamicResource AsyncWorkUserControlStyle}" 9 mc:Ignorable="d"> 10 复制代码 定义基础ViewModel 复制代码 1 /// 2 /// 响应式的ViewModel模型 3 /// 4 public abstract class ViewModelResponsive : ViewModelBase, IViewModelResponsive 5 { 6 #region Fields 7 8 private ViewModelStatus _status = ViewModelStatus.None; 9 10 #endregion 11 12 #region ViewModel Status 13 14 /// 15 /// 刷新UI数据 16 /// 17 public virtual void Refresh() 18 { 19 20 } 21 22 /// 23 /// ViewModel状态 24 /// 25 public ViewModelStatus Status 26 { 27 get 28 { 29 return _status; 30 } 31 protected set 32 { 33 if (_status != value) 34 { 35 _status = value; 36 RaisePropertyChanged(@"Status"); 37 } 38 } 39 } 40 41 #endregion 42 } 复制代码 ViewModel 应用 复制代码 1 public class CameraManagementViewModel : ViewModelResponsive 2 { 3 protected override void BindCommands() 4 { 5 RefreshCommand = new RelayCommand(() => 6 { 7 Refresh(); 8 }); 9 } 10 11 public override void Refresh() 12 { 13 base.Refresh(); 14 15 Status = ViewModelStatus.Initializing; 16 CameraCollection.Clear(); 17 Model.GetCameras(GetCamerasCallback); 18 } 19 20 private void GetCamerasCallback(object sender, AsyncWorkerCallbackEventArgs 21 { 22 CameraCollection.Clear(); 23 Status = ViewModelStatus.Loaded; 24 25 if (result) 26 { 27 foreach (var item in (args.Data as IList 28 { 29 CameraCollection.Add(item); 30 } 31 } 32 } 33 } 复制代码