1、Silverlight入门系列应用MVVM模式10BackgroundWorkder和MVVMSilverlight下这个BackgroundWorker我们应当很熟悉了,以前在WinForms下面就有;当我们需要在当前UI线程之外的线程处理耗时的操作而不阻塞UI线程,就可以用这个BackgroundWorker. 用起来也是很方便,需要注意的是在DoWork事件中不要操作UI线程的内容,把UI操作都放到ReportProgress事件处理和WorkCompleted事件处理中。记住这两点就可以了。今天讲的是Silverlight如何在MVVM模式下用BackgroundWorker。总体原则
2、就是把后台耗时业务处理和界面逻辑分开,既实现多线程,又实现界面和逻辑分离。主要BackgroundWorker代码:ViewModel代码:(里面有个Command启动耗时任务,任务中ReportProgress事件处理和WorkCompleted事件通知UI)1: using System;2: using System.ComponentModel;3: using System.Windows.Input;4: 5: namespace BackgroundWorkerTest6: 7: public class ViewModel : INotifyPropertyChanged8:
3、9: public ICommand StartTaskCommand get; private set; 10: private int _counter = 0;11: 12: public ViewModel()13: 14: StartTaskCommand = new DelegateCommand(StartTask, CanStartTask);15: 16: 17: private void StartTask(object param)18: 19: var backgroundWorker = new BackgroundWorker();20: 21: backgroun
4、dWorker.WorkerSupportsCancellation = true;22: backgroundWorker.WorkerReportsProgress = true;23: 24: backgroundWorker.DoWork += (s, e) =25: 26: for (int i = 0; i 36: 37: CurrentProgress = e.ProgressPercentage;38: CurrentProgressText = e.UserState != null ? e.UserState.ToString() : String.Empty;39: ;4
5、0: 41: backgroundWorker.RunWorkerCompleted += (s, e) =42: 43: CurrentProgress = 100;44: CurrentProgressText = Completed!;45: ;46: 47: backgroundWorker.RunWorkerAsync();48: 49: 50: 51: private bool CanStartTask(object param)52: 53: return true;54: 55: 56: private string _currentProgressText;57: publi
6、c string CurrentProgressText58: 59: get return _currentProgressText; 60: set61: 62: if (_currentProgressText != value)63: 64: _currentProgressText = value;65: 66: if (PropertyChanged != null)67: 68: PropertyChanged(this, new PropertyChangedEventArgs(CurrentProgressText);69: 70: 71: 72: 73: 74: priva
7、te double _currentProgress;75: public double CurrentProgress76: 77: get return _currentProgress; 78: set79: 80: if (_currentProgress != value)81: 82: _currentProgress = value;83: 84: if (PropertyChanged != null)85: 86: PropertyChanged(this, new PropertyChangedEventArgs(CurrentProgress);87: 88: 89: 9
8、0: 91: 92: public event PropertyChangedEventHandler PropertyChanged;93: 94: 95: 96: public class DelegateCommand : ICommand97: 98: 99: / 100: 101: / Occurs when changes occur that affect whether the command should execute.102: 103: / 104: 105: public event EventHandler CanExecuteChanged;106: 107: 10
9、8: 109: Func canExecute;110: 111: Action executeAction;112: 113: bool canExecuteCache;114: 115: 116: 117: / 118: 119: / Initializes a new instance of the class.120: 121: / 122: 123: / The execute action.124: 125: / The can execute.126: 127: public DelegateCommand(Action executeAction,128: 129: Func
10、canExecute)130: 131: 132: this.executeAction = executeAction;133: 134: this.canExecute = canExecute;135: 136: 137: 138: 139: 140: #region ICommand Members141: 142: / 143: 144: / Defines the method that determines whether the command 145: 146: / can execute in its current state.147: 148: / 149: 150:
11、/ 151: 152: / Data used by the command. 153: 154: / If the command does not require data to be passed,155: 156: / this object can be set to null.157: 158: / 159: 160: / 161: 162: / true if this command can be executed; otherwise, false.163: 164: / 165: 166: public bool CanExecute(object parameter)16
12、7: 168: 169: bool tempCanExecute = canExecute(parameter);170: 171: 172: 173: if (canExecuteCache != tempCanExecute)174: 175: 176: canExecuteCache = tempCanExecute;177: 178: if (CanExecuteChanged != null)179: 180: 181: CanExecuteChanged(this, new EventArgs();182: 183: 184: 185: 186: 187: 188: 189: re
13、turn canExecuteCache;190: 191: 192: 193: 194: 195: / 196: 197: / Defines the method to be called when the command is invoked.198: 199: / 200: 201: / 202: 203: / Data used by the command. 204: 205: / If the command does not require data to be passed, 206: 207: / this object can be set to null.208: 20
14、9: / 210: 211: public void Execute(object parameter)212: 213: 214: executeAction(parameter);215: 216: 217: 218: #endregion219: 220: 221: View(Xaml.cs)代码: 1: using System.Windows.Controls; 2: 3: namespace BackgroundWorkerTest 4: 5: public partial class MainPage : UserControl 6: 7: public MainPage() 8
15、: 9: InitializeComponent(); 10: 11: this.DataContext = new ViewModel(); 12: 13: 14: View(Xaml)代码: 1: 8: 9: 10: 11: 12: 13: 14: Dispatcher如果没有使用BackgroundWorker在非UI线程需要调用UI回调的时候,需要调用当前Application的Dispatcher来完成,比如: 1: private void UpdateUI() 2: 3: Dispatcher.BeginInvoke() = 4: 5: ProgressBar.Value = 5
16、0; 6: ); 7: 如果你在一个Class里面(非UserControl),也就是无法获得Application对象的情况下,情况要负责一些,你可以使用一个假的控件对象来构造一个Dummy控件,例如: 1: /以下代码在非UserControl的Class里面: 2: TextBlock _dispatcherObject = new TextBlock(); 3: private void UpdateUINasty() / avoid this approach unless its all youve got 4: 5: _dispatcherObject.Dispatcher.Be
17、ginInvoke() = 6: 7: SomePage.ProgressBar.Value = 50; 8: ); 9: 反之,如果运行在UI线程里面,就不必像上面那样做,最好使用Deployment.Current.Dispatcher对象: 1: private void UpdateUINotSoNasty() 2: 3: Deployment.Current.Dispatcher.BeginInvoke() = 4: 5: SomePage.ProgressBar.Value = 50; 6: ); 7: 当然,最保险的方法是先检查当前线程是否是UI线程,如果不是,那么进行UI操作需
18、要用BeginInvoke: 1: Action myaction = ()=DoSomething(); 2: var dispatch = Deployment.Current.Dispatcher; 3: if (dispatch.CheckedAccess) 4: 5: myaction(); 6: 7: else 8: 9: dispatch.BeginInvoke(myaction(); 10: 代码截图:使用定时器:DispatcherTimer 1: private void StartTimer() 2: 3: DispatcherTimer timer = new DispatcherTimer(); 4: 5: timer.Tick += (s, e) = 6: 7: / do some very quick work here 8: 9: / update the UI 10: StatusText.Text = DateTime.Now.Second.ToString(); 11: ; 12: 13: timer.Interval = TimeSpan.FromSeconds(1); 14: timer.Start(); 15:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1