【发布时间】:2013-06-29 16:11:45
【问题描述】:
我有一个面板,上面有一个按钮,用于触发来自外部摄像头的图像捕获。捕获可能需要几秒钟,因此我希望在捕获过程中禁用该按钮。我还希望能够在我的程序运行控制脚本时阻止用户捕获。这是我的 ViewModel 类:
public class CameraControlViewModel : ViewModelBase
{
public CameraControlViewModel()
{
}
public CameraControlViewModel( DataModel dataModel )
: base( dataModel )
{
dataModel.PropertyChanged += DataModelOnPropertyChanged;
_captureImageCommand = new RelayCommand( captureImage );
_capturedImage = new BitmapImage();
_capturedImage.BeginInit();
_capturedImage.UriSource = new Uri( "Images/fingerprint.jpg", UriKind.Relative );
_capturedImage.CacheOption = BitmapCacheOption.OnLoad;
_capturedImage.EndInit();
}
public ICommand CaptureImageCommand
{
get { return _captureImageCommand; }
}
public bool CanCaptureImage
{
get { return !dataModel.IsScriptRunning && !_captureInProgress; }
}
public bool IsCaptureInProgress
{
get { return _captureInProgress; }
set
{
if (_captureInProgress != value)
{
_captureInProgress = value;
OnPropertyChanged( "IsCaptureInProgress" );
OnPropertyChanged( "CanCaptureImage" );
}
}
}
public int PercentDone
{
get { return _percentDone; }
set
{
if (_percentDone != value)
{
_percentDone = value;
OnPropertyChanged( "PercentDone" );
}
}
}
public BitmapImage CapturedImage
{
get { return _capturedImage; }
}
private void DataModelOnPropertyChanged( object sender, PropertyChangedEventArgs propertyChangedEventArgs )
{
string property = propertyChangedEventArgs.PropertyName;
if (property == "IsScriptRunning")
{
OnPropertyChanged( "CanCaptureImage" );
}
OnPropertyChanged( property );
}
private void captureImage( object arg )
{
IsCaptureInProgress = true;
PercentDone = 0;
// TODO: remove this placeholder.
new FakeImageCapture( this );
// TODO (!)
}
internal void captureComplete()
{
IsCaptureInProgress = false;
}
// Remove this placeholder when we can take images.
private class FakeImageCapture
{
CameraControlViewModel _viewModel;
int _count;
Timer _timer = new Timer();
public FakeImageCapture( CameraControlViewModel viewModel )
{
this._viewModel = viewModel;
_timer.Interval = 50;
_timer.Elapsed += TimerOnTick;
_timer.Start();
}
private void TimerOnTick( object sender, EventArgs eventArgs )
{
++_count;
if (_count <= 100)
{
_viewModel.PercentDone = _count;
}
else
{
Application.Current.Dispatcher.Invoke( (Action)_viewModel.captureComplete );
_timer.Stop();
_timer = null;
_viewModel = null;
}
}
}
private readonly ICommand _captureImageCommand;
private volatile bool _captureInProgress;
private BitmapImage _capturedImage;
private int _percentDone;
}
这是按钮的 XAML:
<Button Command="{Binding CaptureImageCommand}"
Grid.Row="0" Grid.Column="0"
Margin="4"
IsEnabled="{Binding CanCaptureImage}"
ToolTip="Capture Image">
<Image Source="../Images/camera-icon.gif" Width="64" Height="64" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Button>
单击“捕获”按钮即可。该按钮禁用,并在其他地方出现一个进度条,显示(当前伪造的)图像捕获进度。但是,当捕获完成时,即使我在 captureComplete() 方法中设置了 CanCaptureImage 属性,按钮也不会变回其“启用”外观。只有当我单击窗口中的某个地方(任何地方)时,它才会这样做。但是,该按钮实际上已启用,因为我可以再次单击它来触发第二次捕获。
我在captureComplete() 中尝试过CommandManager.InvalidateRequerySuggested(),但这并没有帮助。有什么想法吗?
【问题讨论】:
-
你确定脚本没有还在运行吗?
-
当然,@ErnodeWeerd。
-
当您在 CanCaptureImage getter 上设置断点时,是否在捕获完成后对其进行评估?必须向 UI 发出信号,表明应该重新评估 CanCaptureImage...
-
也许您可以在更改值后尝试在 IsCaptureInProgress 属性设置器中引发 CaptureImageCommand 的 ICommand.CanExecuteChanged 事件。
-
@ErnodeWeerd 是的,该属性正在正确评估。但是在我单击其他地方之前,按钮仍然不会刷新。我认为这可能与我的按钮样式有关,但我将其全部关闭,默认视觉效果仍然会发生这种情况。