需求描述
- 在 ViewModel 中处理 Model 中的数据需要一定时间的等待;
- ViewModel 或 Model 在获取数据或访问同步服务时有一定延迟需要等待;
- ViewModel 操作 View 加载数据需要一段时间;
解决办法
- 显示一个等待 UI,当数据处理完毕或服务接口返回后等待UI消失
转动齿轮控件
- 参考开源实现 SprocketControl :http://wpfspark.codeplex.com/
等待控件
1 <Grid> 2 <local:SprocketControl Grid.Row="0" 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 </Grid>
等待效果
定义 MVVM 中的 ViewModel 的状态
/// <summary> /// 在MVVM模式中ViewModel的状态 /// </summary> [Flags] public enum ViewModelStatus { /// <summary> /// ViewModel无状态 /// </summary> None = 0x0, /// <summary> /// ViewModel正在初始化 /// </summary> Initializing = 0x1, /// <summary> /// ViewModel初始化完毕 /// </summary> Initialized = 0x2, /// <summary> /// ViewModel正在加载 /// </summary> Loading = 0x4, /// <summary> /// ViewModel加载完毕 /// </summary> Loaded = 0x8, /// <summary> /// ViewModel正在保存 /// </summary> Saving = 0x16, /// <summary> /// ViewModel保存完毕 /// </summary> 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 <coverters:StatusToAnimationVisibilityConverter x:Key="StatusToAnimationVisibilityConverter" /> 2 3 <Style x:Key="AsyncWorkUserControlStyle" TargetType="{x:Type UserControl}"> 4 <Setter Property="Template"> 5 <Setter.Value> 6 <ControlTemplate TargetType="{x:Type UserControl}"> 7 <Grid> 8 <ContentPresenter Panel.ZIndex="0" /> 9 <Grid x:Name="animationGrid" 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 <Grid Width="Auto" 18 Height="Auto" 19 HorizontalAlignment="Stretch" 20 VerticalAlignment="Stretch" 21 Panel.ZIndex="0" 22 Background="{DynamicResource MaskGridBackgroundBrush}" 23 Opacity="0.2" /> 24 <ctrl:WaitingControl x:Name="animation" Panel.ZIndex="1" /> 25 </Grid> 26 </Grid> 27 </ControlTemplate> 28 </Setter.Value> 29 </Setter> 30 </Style>
应用 Style 至 UserControl
1 <UserControl x:Class="DeviceConfiguration.Views.CameraManagementView" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 d:DesignHeight="318" 7 d:DesignWidth="632" 8 Style="{DynamicResource AsyncWorkUserControlStyle}" 9 mc:Ignorable="d"> 10 </UserControl>
定义基础 ViewModel
1 /// <summary> 2 /// 响应式的ViewModel模型 3 /// </summary> 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 /// <summary> 15 /// 刷新UI数据 16 /// </summary> 17 public virtual void Refresh() 18 { 19 20 } 21 22 /// <summary> 23 /// ViewModel状态 24 /// </summary> 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<IList<Camera>> args) 21 { 22 CameraCollection.Clear(); 23 Status = ViewModelStatus.Loaded; 24 25 if (result) 26 { 27 foreach (var item in (args.Data as IList<Camera>)) 28 { 29 CameraCollection.Add(item); 30 } 31 } 32 } 33 }
实现效果
本文转自匠心十年博客园博客,原文链接:XXXXXXXX,如需转载请自行联系原作者