在这里,我们将控制进度条的进度显示,功能很简单,通过两个按钮“Start”和“Stop”分别控制进度条的加载与暂停,当Start可用时,Stop不可用;反之,当Start不可用时,Stop可用。
我们知道,当UI绑定Command时会订阅CanExecuteChanged事件,而该事件会一直监测UI的状态并实时调用CanExecute方法返回其状态,同样的,我们在之前MVVM的基础上来实现这一功能。
1、在Model里添加Progress类
class Progress
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public double Value { get; set; }
public string Text { get; set; }
}
2、在Command里添加两个类,RelayCommandGo和RelayCommandStop
class RelayCommandGo : ICommand
{
private Action _execute;
private Func<bool> _canExecute;
public RelayCommandGo(Action execute, Func<bool> canExecute)
{
this._execute = execute;
this._canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return this._canExecute();
}
public void Execute(object parameter)
{
this._execute();
}
}
class RelayCommandStop : ICommand
{
private Action _execute;
private Func<bool> _canExecute;
public RelayCommandStop(Action execute, Func<bool> canExecute)
{
this._execute = execute;
this._canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return this._canExecute();
}
public void Execute(object parameter)
{
this._execute();
}
}
3、在ViewModel里添加ProgressViewModel类
namespace MVVM3
{
class ProgressViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Progress Progress { get; set; }
/// <summary>
/// 最小值
/// </summary>
public double Minimum
{
get { return this.Progress.Minimum; }
set
{
this.Progress.Minimum = value;
RaisePropertyChanged("Minimum");
}
}
/// <summary>
/// 最大值
/// </summary>
public double Maximum
{
get { return this.Progress.Maximum; }
set
{
this.Progress.Maximum = value;
RaisePropertyChanged("Maximum");
}
}
/// <summary>
/// 当前数值
/// </summary>
public double Value
{
get { return this.Progress.Value; }
set
{
this.Progress.Value = value;
RaisePropertyChanged("Value");
}
}
/// <summary>
/// 当前数值
/// </summary>
public string Text
{
get { return this.Progress.Text; }
set
{
this.Progress.Text = value;
RaisePropertyChanged("Text");
}
}
/// <summary>
/// 是否可用的状态
/// </summary>
public bool IsEnabledStart { get; set; }
/// <summary>
/// 是否可用的状态
/// </summary>
public bool IsEnabledStop { get; set; }
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public RelayCommandGo CommandGo { get; set; }
public RelayCommandStop CommandStop { get; set; }
/// <summary>
/// 线程同步事件
/// </summary>
private ManualResetEvent _manualReset;
/// <summary>
/// 线程
/// </summary>
private Thread _thread;
public ProgressViewModel()
{
this.Progress = new Progress() { Maximum = 100 };
this._manualReset = new ManualResetEvent(false);
this.IsEnabledStart = true;
this.IsEnabledStop = false;
this.CommandGo = new RelayCommandGo(StartProgress, EnabledStart);
this.CommandStop = new RelayCommandStop(StopProgress, EnabledStop);
}
/// <summary>
/// 开启线程
/// </summary>
private void StartProgress()
{
this._manualReset.Set();
if (_thread == null)
{
_thread = new Thread(new ThreadStart(() =>
{
for (int i = 1; i <= 100; i++)
{
this._manualReset.WaitOne();
this.Value = i;
this.Text = string.Format("{0}%", i);
Thread.Sleep(200);
}
}));
_thread.Start();
}
this.IsEnabledStop = this.IsEnabledStart;
this.IsEnabledStart = !this.IsEnabledStart;
}
/// <summary>
/// 停止线程的执行
/// </summary>
private void StopProgress()
{
this._manualReset.Reset();
this.IsEnabledStart = this.IsEnabledStop;
this.IsEnabledStop = !this.IsEnabledStop;
}
/// <summary>
/// 确定此命令是否可以在当前状态下执行
/// </summary>
/// <returns></returns>
private bool EnabledStart()
{
return this.IsEnabledStart;
}
/// <summary>
/// 确定此命令是否可以在当前状态下执行
/// </summary>
/// <returns></returns>
private bool EnabledStop()
{
return this.IsEnabledStop;
}
}
}
4、在View里添加xaml
<Window x:Class="MVVM3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MVVM3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ProgressViewModel x:Key="progressViewModel"></local:ProgressViewModel>
</Window.Resources>
<Window.DataContext>
<Binding Source="{StaticResource ResourceKey=progressViewModel}"></Binding>
</Window.DataContext>
<StackPanel>
<TextBlock x:Name="tb" Height="23" Text="{Binding Text}"></TextBlock>
<ProgressBar x:Name="pb" Height="20" Minimum="{Binding Minimum}" Maximum="{Binding Maximum}" Value="{Binding Value}"></ProgressBar>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Start" Width="72" Height="23" Margin="5" Command="{Binding CommandGo}"></Button>
<Button Content="Stop" Width="72" Height="23" Margin="5" Command="{Binding CommandStop}"></Button>
</StackPanel>
</StackPanel>
</Window>
(1)、程序启动时
(2)、点击Start
(3)、点击Stop