快速笔记,这样我就不会浪费任何人的时间。从nuget安装MVVMLight时,我最终收到一个错误
null : The term 'null' is not recognized as the name of a cmdlet, function, script file, or operable program
.MVVMLight似乎可以正常工作,除了下面将描述的问题,但我想提一下这一点以防万一。
问题
我遇到了一个问题,命令执行完成后按钮无法重新启用。如果执行速度很快,它们似乎有时会起作用,但任何需要一段时间的操作似乎永远不会起作用。这是种族状况的尖叫。
我正在使用Task执行冗长的操作,以便UI可以更新。任务的第一步和最后一步是适当地翻转IsBusy(其中每个CanExecute方法
returns !IsBusy;
)
我构建了一个将使用Thread的简单示例。睡眠模拟缓慢的操作,它很好地展示了问题。这个
WaitOneSecondCommand
似乎间歇性工作。这个
WaitTenSecondsCommand
和
WaitThirtySecondsCommand
永远不要工作。
通过
不工作
我的意思是,按钮一直处于禁用状态,直到我单击窗体上的某个位置。
我尝试过的事情
我已经做了大量的研究,迄今为止我尝试的解决方案并没有改变这种行为。我最终导致了暴力强迫所有不同的“修复”,以防我误解。
我尝试的一件事是扩展RelayCommands以引发属性更改。例如:
发件人:
public RelayCommand WaitOneSecondCommand {
get; set;
}
收件人:
public RelayCommand WaitTenSecondsCommand {
get {
return _waitTenSecondsCommand;
}
set {
_waitTenSecondsCommand = value;
RaisePropertyChanged();
}
}
我没想到它会起作用,但我想试试。我还尝试添加
WaitTenSecondsCommand.RaiseCanExecuteChanged();
我还尝试添加
WaitTenSecondsCommand.RaiseCanExecuteChanged()
CommandExecute方法,但这也没有改变任何东西。
private void WaitTenSecondsCommandExecute() {
Task.Run(() => {
IsBusy = true;
Thread.Sleep(10000);
IsBusy = false;
WaitTenSecondsCommand.RaiseCanExecuteChanged();
});
}
我还读到了CommandManager,所以我补充道
CommandManager.InvalidateRequerySuggested()
也我把它添加到IsBusy中,以为这会很垃圾,但我认为这会消除任何疑问
这又是一种竞争条件的味道,我在这里使用的是Task,但这些任务不能同时运行,并且由于使用了IsBusy标志而不能相互冲突。
完整代码
这是一个使用.Net 4.6.1的基本WPF应用程序,从Nuget安装了MVVMLight 5.2.0。
主窗口.xaml
<Window x:Class="StackOverflowExample.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" MinHeight="100" Width="150" ResizeMode="NoResize" SizeToContent="Height"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<StackPanel>
<Button Height="70" Margin="5" Command="{Binding WaitOneSecondCommand}">Wait 1 Second</Button>
<Button Height="70" Margin="5" Command="{Binding WaitTenSecondsCommand}">Wait 10 Seconds</Button>
<Button Height="70" Margin="5" Command="{Binding WaitThirtySecondsCommand}">Wait 30 Seconds</Button>
</StackPanel>
<Grid>
<Label HorizontalAlignment="Left" Width="84">IsBusy:</Label>
<TextBox IsReadOnly="True" HorizontalAlignment="Right" Width="45" Text="{Binding IsBusy}" Margin="4,5,5,5" />
</Grid>
</Window>
我添加了IsBusy的绑定,以清楚地显示它正在正确更新。这也是了解10秒和30秒命令何时完成的唯一可靠方法。我不希望任何MessageBox强制您单击“确定”导致CanExecute更新。这是一个创可贴。
主视图模型.cs
public class MainViewModel : ViewModelBase {
private bool _isBusy;
private RelayCommand _waitTenSecondsCommand;
public MainViewModel() {
WaitOneSecondCommand = new RelayCommand(WaitOneSecondCommandExecute, WaitOneSecondCommandCanExecute);
WaitTenSecondsCommand = new RelayCommand(WaitTenSecondsCommandExecute, WaitTenSecondsCommandCanExecute);
WaitThirtySecondsCommand = new RelayCommand(WaitThirtySecondsCommandExecute, WaitThirtySecondsCommandCanExecute);
}
public RelayCommand WaitOneSecondCommand {
get; set;
}
public RelayCommand WaitTenSecondsCommand {
get {
return _waitTenSecondsCommand;
}
set {
_waitTenSecondsCommand = value;
RaisePropertyChanged();
WaitTenSecondsCommand.RaiseCanExecuteChanged();
}
}
public RelayCommand WaitThirtySecondsCommand {
get; set;
}
public bool IsBusy {
get {
return _isBusy;
}
set {
_isBusy = value;
RaisePropertyChanged();
CommandManager.InvalidateRequerySuggested();
}
}
private void WaitOneSecondCommandExecute() {
Task.Run(() => {
IsBusy = true;
Thread.Sleep(1000);
IsBusy = false;
});
}
private void WaitTenSecondsCommandExecute() {
Task.Run(() => {
IsBusy = true;
Thread.Sleep(10000);
IsBusy = false;
WaitTenSecondsCommand.RaiseCanExecuteChanged();
});
}
private void WaitThirtySecondsCommandExecute() {
Task.Run(() => {
IsBusy = true;
Thread.Sleep(30000);
IsBusy = false;
});
}
private bool WaitOneSecondCommandCanExecute() {
return !IsBusy;
}
private bool WaitTenSecondsCommandCanExecute() {
return !IsBusy;
}
private bool WaitThirtySecondsCommandCanExecute() {
return !IsBusy;
}
}
请注意,在视图模型中,我只在WaitTenSeconds上添加了一个支持字段,以表明它不会改变行为。