MVVMLight學習筆記(六)---DispatchHelper更新UI

1、概述異步

在應用程序中,線程能夠被看作是應用程序的一個較小的執行單位。每一個應用程序都至少擁有一個線程,咱們稱爲主線程。當調用和操做主線程的時候,該操做將動做添加到一個隊列中,每一個操做均按照將它們添加到隊列中的順序連續執行,可是能夠經過爲這些動做指定優先級來影響執行順序,而負責管理此隊列的對象稱之爲線程調度程序。函數

咱們知道,WPF程序中,控件是屬於UI線程的,若是試圖在子線程中訪問或者更新UI,就須要在子線程中通知主線程來處理UI, 經過向主線程的Dispatcher隊列註冊工做項,來通知UI線程更新結果。this

Dispatcher提供兩個註冊工做項的方法:Invoke 和 BeginInvoke。spa

這兩個方法均調度一個委託來執行。Invoke 是同步調用,也就是說,直到 UI 線程實際執行完該委託它才返回。BeginInvoke是異步的,將當即返回。線程

代碼片斷以下:code

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


2、MVVMLight模式下ViewModel中更新UIcomponent

一般狀況下,ViewModel 不從 DispatcherObject 繼承,不能訪問 Dispatcher 屬性。這時候,咱們須要使用DispatcherHelper 組件來更新UI。對象

實際上,該類所作的是將主線程的調度程序保存在靜態屬性中,並公開一些實用的方法,以便經過統一的方式訪問。blog

爲了實現正常功能,須要在主線程上初始化該類。繼承

一般,在 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
    }
}
相關文章
相關標籤/搜索