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
- }
- }
MVVMLight学习笔记(六)---DispatchHelper更新UI的更多相关文章
- [Android学习笔记]子线程更新UI线程方法之Handler
关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...
- python3.4学习笔记(六) 常用快捷键使用技巧,持续更新
python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...
- # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)
目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...
- HTML语言学习笔记(会更新)
# HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记六:接口
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Go语言学习笔记六: 循环语句
Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...
- 【opencv学习笔记六】图像的ROI区域选择与复制
图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...
随机推荐
- WIN7 WIN10修改path不用重启即可生效
近来安装python scrapy经常忘了添加到path,需要时增加了但需要重启才能起作用,用下面的方法马上能生效: 1修改path:右击"计算机"--高级--环境变量--path ...
- java网络编程基础——TCP网络编程三
AIO实现非阻塞通信 java7 NIO2 提供了异步Channel支持,这种异步Channel可以提供更高效的IO,这种基于异步Channel的IO被称为异步IO(Asynchronous IO) ...
- 使用vlookup的模糊匹配和字符串拼接
1,=IF(ISNA(VLOOKUP("*"&$D2&"*",$A$2:$A$43,1,FALSE))=FALSE,TRUE,FALSE) 2, ...
- div标签width:auto无效
1,因为div标签默认是display:block,独占一行,宽度为父元素的100%,但是高度是auto,跟随内部内容而定.所以要想 设值父元素随子元素的宽高,那么就要设置div标签为display: ...
- python基础之文件的读取
#文件名 txt文件的读取#文件的读取 open("文件","读写方法") with open("文件","读写方法") ...
- 从源码构建Vim
从源码构建Vim 引言 事情是介样滴,因为我是个Vim 重度使用者了差不多.. 但在大部分系统上能安装到的或者自带的都是比较老的版本,可能是7.x 之类的.也或者是你需要使用到Vim 的某些特性或者功 ...
- 看懂UML类图笔记
在学习设计模式的时候,经常会遇到UML类图,所以就找了一些资料,做一些笔记. 从一个示例开始 下面这个类图,类之间的关系是我们需要关注的: 车的类图结构为<<abstract>> ...
- 【模拟】选数 luogu-1037
AC代码 #include <bits/stdc++.h> using namespace std; #define ms(a,b) memset(a,b,sizeof(a)) typed ...
- 裸奔mysql
centos 7 下裸奔mysql # vim /etc/my.cnf在[mysqld]的段中加上一句:skip-grant-tables例如:[mysqld]datadir=/var/lib/mys ...
- 双击映射坚果云网盘并打开的AHK源代码
双击映射坚果云网盘并打开的AHK源代码 #SingleInstance,force ;当此脚本已经运行时自动替换旧实例再次运行.#Persistent ;让脚本持久运行(即直到用户关闭或遇到 Exit ...