好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何在ViewModel中正确地使用Timer(定时器)

如何在ViewModel中正确地使用Timer(定时器)

内容摘要:

这是我在某个客户那边讲课的时候遇到一个小问题,在ViewModel中创建的一个Timer,并不会被自动停止,即便使用该ViewModel的View已经被关闭了。这个问题的原因在于Timer的特殊工作机制,它是运行在一个独立的工作线程的,除非明确地停止他,或者整个程序关闭了,它才会停止。这一讲中,我通过实例重现了这个问题,然后提供了一个可行的解决方法。

视频地址:

http://www.tudou.com/programs/view/uO4b2j0N4L8/

示例代码:

备注:该范例使用了MvvmLight作为MVVM框架,请自行安装

Model:

 using  System;
 using  System.Diagnostics;
 using  System.Linq;

 namespace  SilverlightApplicationSample
{
     public   class  DataService
    {
         public   static  Customer[] GetCustomers()
        {

            Debug.WriteLine( string .Format( "[{0}]正在调用数据服务" ,DateTime.Now));

            var rnd =  new  Random();
             return  Enumerable.Range(1, rnd.Next(100)).Select(x =>  new  Customer()
            {
                CompanyName =  "Company "  + x.ToString()
            }).ToArray();

        }
    }

     public   class  Customer
    {
         public   string  CompanyName { get; set; }
    }
}
 
 ViewModel: 
 using  System;
 using  System.Windows.Threading;
 using  GalaSoft.MvvmLight;

 namespace  SilverlightApplicationSample
{
     /// <summary> 
     /// 使用MVVMLight实现的MVVM ViewModel 
     /// </summary> 
     public   class  CustomerWindowViewModel : ViewModelBase
    {
         /// <summary> 
         /// 这个方法也不会自动调用 
         /// </summary> 
         public   override   void  Cleanup()
        {
             base .Cleanup();

            timer.Stop();
        }

 

        DispatcherTimer timer =  null ;

         public  CustomerWindowViewModel()
        {
             //正常情况下的绑定 
             //Customers = DataService.GetCustomers(); 


             //使用定时器调用服务 
            timer =  new  DispatcherTimer();

            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += (o, a) =>
            {
                Customers = DataService.GetCustomers();
            };

            timer.Start();
        }

         private  Customer[] _Customers;
         public  Customer[] Customers
        {
            get {  return  _Customers; }
            set
            {
                 if  (_Customers !=  value )
                {
                    _Customers =  value ;
                    RaisePropertyChanged( "Customers" );
                }
            }
        }
    }
}

View:

 <  controls:ChildWindow   x:Class  ="SilverlightApplicationSample.CustomerWindow" 
                       xmlns  ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                       xmlns:x  ="http://schemas.microsoft.com/winfx/2006/xaml" 
                       xmlns:controls  ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" 
                       Width  ="400" 
                       Height  ="300" 
                       Title  ="CustomerWindow" 
                       xmlns:local  ="clr-namespace:SilverlightApplicationSample"  > 
     <  controls:ChildWindow.DataContext  > 
         <  local:CustomerWindowViewModel  ></  local:CustomerWindowViewModel  > 
     </  controls:ChildWindow.DataContext  > 
    
     <  Grid   x:Name  ="LayoutRoot" 
           Margin  ="2"  > 
         <  Grid.RowDefinitions  > 
             <  RowDefinition   /> 
             <  RowDefinition   Height  ="Auto"   /> 
         </  Grid.RowDefinitions  > 



         <  ListBox   ItemsSource  ="{Binding Customers}" 
                  DisplayMemberPath  ="CompanyName"  > 
         </  ListBox  > 

         <  Button   x:Name  ="CancelButton" 
                 Content  ="Cancel" 
                 Click  ="CancelButton_Click" 
                 Width  ="75" 
                 Height  ="23" 
                 HorizontalAlignment  ="Right" 
                 Margin  ="0,12,0,0" 
                 Grid . Row  ="1"   /> 
         <  Button   x:Name  ="OKButton" 
                 Content  ="OK" 
                 Click  ="OKButton_Click" 
                 Width  ="75" 
                 Height  ="23" 
                 HorizontalAlignment  ="Right" 
                 Margin  ="0,12,79,0" 
                 Grid . Row  ="1"   /> 
     </  Grid  > 
 </  controls:ChildWindow  > 
 
 
Page:
 using  System.Windows;
 using  System.Windows.Controls;

 namespace  SilverlightApplicationSample
{
     public   partial   class  MainPage : UserControl
    {
         public  MainPage()
        {
            InitializeComponent();
        }

        

         private   void  Button_Click( object  sender, RoutedEventArgs e)
        {
            var window =  new  CustomerWindow();
            window.Closed += (o, a) =>
            {
                var vm = window.DataContext  as  CustomerWindowViewModel;
                vm.Cleanup();
            };

            window.Show();
        }
    }
}

分类:  WPF或者Silverligh ,  fmplan-02 - Developement Practice-02-1-Desktop

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于如何在ViewModel中正确地使用Timer(定时器)的详细内容...

  阅读:43次