• WPF异步MVVM等待窗体


    需求描述

    • 在 ViewModel 中处理 Model 中的数据需要一定时间的等待;
    • ViewModel 或 Model 在获取数据或访问同步服务时有一定延迟需要等待;
    • ViewModel 操作 View 加载数据需要一段时间;

    解决办法

    • 显示一个等待 UI,当数据处理完毕或服务接口返回后等待UI消失

    转动齿轮控件

    等待控件

     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   }

    实现效果

  • 相关阅读:
    [BZOJ2839:]集合计数
    [BZOJ2863:]愤怒的元首
    [BZOJ:3162]:独钓寒江雪
    PHP数据库基础(简单的)
    PHP数组创建和遍历(基础)
    中缀表达式转换为前、后缀表达式转化简单的技巧[转]
    PHP网页简单的计算机源代码
    JS确认取消按钮使用
    js(JavaScript)使用${pageContext.request.contextPath}报错
    易游验证怎么配置?易游验证怎么使用!!
  • 原文地址:https://www.cnblogs.com/gaochundong/p/wpf_mvvm_async_waiting_view.html
Copyright © 2020-2023  润新知