zoukankan      html  css  js  c++  java
  • MVVMLight学习笔记(六)DispatchHelper更新UI

    一、概述

    在应用程序中,线程可以被看做是应用程序的一个较小的执行单位。每个应用程序都至少拥有一个线程,我们称为主线程。当调用和操作主线程的时候,该操作将动作添加到一个队列中,每个操作均按照将它们添加到队列中的顺序连续执行,但是可以通过为这些动作指定优先级来影响执行顺序,而负责管理此队列的对象称之为线程调度程序。

    我们知道,WPF程序中,控件是属于UI线程的,如果试图在子线程中访问或者更新UI,就需要在子线程中通知主线程来处理UI, 通过向主线程的Dispatcher队列注册工作项,来通知UI线程更新结果。

    Dispatcher提供两个注册工作项的方法:Invoke 和 BeginInvoke。

    这两个方法均调度一个委托来执行。Invoke 是同步调用,也就是说,直到 UI 线程实际执行完该委托它才返回。BeginInvoke是异步的,将立即返回。

    代码片段如下:

     this.Dispatcher.BeginInvoke((Action)delegate()
                {
                    更新UI控件ing;
    });


    二、MVVMLight模式下ViewModel中更新UI

    通常情况下,ViewModel 不从 DispatcherObject 继承,不能访问 Dispatcher 属性。这时候,我们需要使用DispatcherHelper 组件来更新UI。

    实际上,该类所做的是将主线程的调度程序保存在静态属性中,并公开一些实用的方法,以便通过统一的方式访问。

    为了实现正常功能,需要在主线程上初始化该类。

    通常,在 MVVM Light 应用程序中,DispatcherHelper 可以在 App.xaml.cs 或者ViewModel的构造函数中进行初始化,App.xaml.cs 是定义应用程序启动类的文件。

    在 WPF 中,该类一般是在 App 构造函数中进行初始化的。

    DispatcherHelper组件初始化以后,DispatcherHelper 类的 UIDispatcher 属性包含对主线程的调度程序的引用。

    但是一般很少直接使用该属性,虽然确实可以使用。通常我们会使用 CheckBeginInvokeOnUi 方法来更新UI。

    代码片段如下:

    复制代码
    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    using GalaSoft.MvvmLight.Threading;
    using MvvmLightClosableTabControl.Models;
    using MvvmLightClosableTabControl.Pages;
    using System;
    using System.Collections.ObjectModel;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Threading;
    
    namespace MvvmLightClosableTabControl.ViewModel
    {
        public class MainViewModel : ViewModelBase
        {
            private ObservableCollection<TabItemModel> tabItemsList = new ObservableCollection<TabItemModel>()
            {
                  new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\1.png",Uri="\\Pages\\Page1.xaml",IsSelected=true , Header="TabItem1" },
                  new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\2.png",Uri="\\Pages\\Page2.xaml",IsSelected=false, Header="TabItem2" },
                  new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\3.png",Uri="\\Pages\\Page3.xaml",IsSelected=false, Header="TabItem3" },
                  new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\4.png",Uri="\\Pages\\Page4.xaml",IsSelected=false, Header="TabItem4" },
            };
    
            public ObservableCollection<TabItemModel> TabItemsList
            {
                get { return tabItemsList; }
                set { tabItemsList = value; RaisePropertyChanged(() => TabItemsList); }
            }
    
            public MainViewModel()
            {
                DispatcherHelper.Initialize();
            }
    
            #region Command
            
            private RelayCommand closeCurrentTabItemCommand;
    
            public RelayCommand CloseCurrentTabItemCommand
            {
                get
                {
                    if (closeCurrentTabItemCommand == null)
                    {
                        closeCurrentTabItemCommand = new RelayCommand(CloseCurrentTabItemImpl);
                    }
                    return closeCurrentTabItemCommand;
                }
                set { closeCurrentTabItemCommand = value; }
            }
            private void CloseCurrentTabItemImpl()
            {
                foreach(var item in TabItemsList)
                {
                    if(item.IsSelected == true)
                    {
                        TabItemsList.Remove(item);
                        break;
                    }
                }
                
            }
    
            //传递一个字符串参数的命令
            private RelayCommand<string> addPageCommand;
    
            public RelayCommand<string> AddPageCommand
            {
                get
                {
                    if (addPageCommand == null)
                    {
                        addPageCommand = new RelayCommand<string>(AddPage);
                    }
                    return addPageCommand;
                }
                set { addPageCommand = value; }
            }
            private void AddPage(string page)
            {
                try
                {
                    TabItemModel myTabItemModel = new TabItemModel() { Img = $"\\MvvmLightClosableTabControl;component\\Img\\{page[4]}.png", Uri = $"\\Pages\\{page}.xaml", IsSelected = true, Header = page };
                   Task.Run( () => DispatcherHelper.CheckBeginInvokeOnUI( () => { TabItemsList.Add(myTabItemModel); } ));//故意在子线程中添加,为了使用DispatcherHelper,在子线程中访问UI
                }
                catch (AggregateException err)
                {
                    foreach (var iem in err.InnerExceptions)
                    {
                        string msg = $"{iem.GetType()}{iem.Source}{iem.Message}";
                        MessageBox.Show(msg);
                    }
            
                }
    
            }
    
            //传递事件参数的命令
            private RelayCommand<MouseButtonEventArgs> tabItemMouseDoubleClickCommand;
    
            public RelayCommand<MouseButtonEventArgs> TabItemMouseDoubleClickCommand
            {
                get
                {
                    if (tabItemMouseDoubleClickCommand == null)
                    {
                        tabItemMouseDoubleClickCommand = new RelayCommand<MouseButtonEventArgs>(TabItemMouseDoubleClickImpl);
                    }
                    return tabItemMouseDoubleClickCommand;
                }
                set { tabItemMouseDoubleClickCommand = value; }
            }
            private int _clickCnt = 0;
            private void TabItemMouseDoubleClickImpl(MouseButtonEventArgs e)
            {
                _clickCnt += 1;
    
                DispatcherTimer timer = new DispatcherTimer();
    
                timer.Interval = new TimeSpan(0, 0, 0, 0, 300);
    
                timer.Tick += (s, e1) => { timer.IsEnabled = false; _clickCnt = 0; };
    
                timer.IsEnabled = true;
                if (_clickCnt %2 == 0)
                {
                    foreach (var item in TabItemsList)
                    {
                        if (item.IsSelected == true)
                        {
                            TabItemsList.Remove(item);
                            PageWindow win = new PageWindow();
                            win.frm.Source = new System.Uri(item.Uri, UriKind.Relative);
                            win.Title = item.Header;
                            win.Show();
                            break;
                        }
                    }
                }
            }
            #endregion
        }
    }
  • 相关阅读:
    new和malloc的区别
    C++中的数据类型强制转换方法
    C++中pair和make_pair的区别
    PlantUML 图绘制类库--VSCODE插件
    Exception: HOUR_OF_DAY: 0 -> 1的问题
    Fiddler手机抓包工具如何设置过滤域名
    MySQL 正则表达式 REGEXP
    ASP.NET Web API 2 中的属性路由
    windows服务搭建(VS2019创建Windows服务不显示安装组件)
    JWT的验证(转载)
  • 原文地址:https://www.cnblogs.com/lzjsky/p/15682805.html
Copyright © 2011-2022 走看看