MVVM中轻松控制ProgressBar

MVVM中要控制进度条其实很方便,但是在开始之前我们要解决一个线程问题。
首先WPF的应用程序至少有连个线程,一个是管理UI的线程,一个是绘制UI的线程。我们需要实现类似复制进度的完成率显示,复制线程不能和UI线程相同,否则顾此失彼。一定要创建一个新线程执行操作。通常我们使用Thread类来实现,这次我使用了线程池ThreadPool来实现。

见截图:


窗体代码(窗体上加三个控件ProgressBar+TextBlock+Button):
<Window x:Class="ProgressDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:ProgressDemo" Title="MainWindow" MinHeight="117" MinWidth="290" MaxHeight="117" Width="441"> <Window.DataContext> <vm:MainWindowViewModel /> </Window.DataContext> <Grid> <ProgressBar Height="22" Margin="20,12,12,0" VerticalAlignment="Top" Value="{Binding Schedule}"/> <TextBlock Height="23" HorizontalAlignment="Left" Margin="20,43,0,0" VerticalAlignment="Top" Text="{Binding Message}"/> <Button Content="Start" Height="23" Margin="0,43,12,0" Name="button1" VerticalAlignment="Top" HorizontalAlignment="Right" Width="75" Command="{Binding CopyCommand}"/> </Grid> </Window>
ViewModel代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Windows.Input; using Microsoft.Practices.Prism.Commands; using System.Threading; namespace ProgressDemo { public class MainWindowViewModel:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private double _schedule; ///<summary> ///进度百分比 ///</summary> public double Schedule { get { return _schedule; } set { if (_schedule != value) { _schedule = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Schedule")); } } } private string _message; ///<summary> ///显示的消息 ///</summary> public string Message { get { return _message; } set { if (_message != value) { _message = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Message")); } } } /// <summary> /// 模拟复制命令 /// </summary> public ICommand CopyCommand { get { return new DelegateCommand(() => { Random random = new Random(); int count = random.Next(5000, 10000); //使用线程池执行 ThreadPool.QueueUserWorkItem( new WaitCallback(obj => { for (int i = 1; i <= count; i++) { /* * 更新: * 1.完成进度的百分比 * 2.消息文字 * 3.按钮的状态 */ Schedule = i * 100.0 / count; Message = string.Format("{0:0.0}% completed.", Schedule); if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("CopyCommand")); Thread.Sleep(1); } }) ); }, ()=>{ //返回按钮状态是否CanExcute return Schedule == 0 || Schedule == 100; }); } } } }


注意:
1.ViewModel实现了INotifyPropertyChanged接口,目的通知View数据的更改;
2.CopyCommand是模拟了复制大文件的操作,先创建了一个随机数,相当于文件的大小,然后用循环模拟复制进度。
ThreadPool.QueueUserWorkItem是执行线程池操作,并执行new WaitCallBack中的委托,此处我采用Lambda委托方式,直接将委托的方法代码写在回调函数中,这样的好处是能直接使用变量count,而不需要再传递到方法中;方法中还使用了Thread.Sleep(1),让线程池中的线程暂停1ms,目的不让程序跑得太快。每一次操作中,还更新了两个控件的显示内容,以及按钮的可用状态。
3.DelegateCommand是Prism中的类,需要引用Microsoft.Practices.Prism.dll

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值