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
        }
    }
  • 相关阅读:
    android 多线程
    Uva 10881 Piotr’s Ants 蚂蚁
    LA 3708 Graveyard 墓地雕塑 NEERC 2006
    UVa 11300 Spreading the Wealth 分金币
    UVa 11729 Commando War 突击战
    UVa 11292 The Dragon of Loowater 勇者斗恶龙
    HDU 4162 Shape Number
    HDU 1869 六度分离
    HDU 1041 Computer Transformation
    利用可变参数函数清空多个数组
  • 原文地址:https://www.cnblogs.com/3xiaolonglong/p/10031424.html
Copyright © 2011-2022 走看看