C# WPF/MVVM在我单击窗口之前不会更新
我有一个面板,上面有一个按钮,用来触发外部摄像头的图像捕获。捕获可能需要几秒钟,因此我希望在捕获过程中禁用该按钮。我还希望在我的程序运行控制脚本时能够防止用户捕获。以下是我的ViewModel类:C# WPF/MVVM在我单击窗口之前不会更新,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个面板,上面有一个按钮,用来触发外部摄像头的图像捕获。捕获可能需要几秒钟,因此我希望在捕获过程中禁用该按钮。我还希望在我的程序运行控制脚本时能够防止用户捕获。以下是我的ViewModel类: public class CameraControlViewModel : ViewModelBase { public CameraControlViewModel() { } public CameraControlViewModel( DataModel da
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;
}
公共类CameraControlViewModel:ViewModelBase
{
公共CameraControlViewModel()
{
}
公共摄像机控制器视图模型(数据模型数据模型)
:基本(数据模型)
{
dataModel.PropertyChanged+=DataModelOnPropertyChanged;
_captureImageCommand=新的RelayCommand(captureImage);
_capturedImage=新的位图图像();
_capturedImage.BeginInit();
_capturedImage.UriSource=新Uri(“Images/fingerprint.jpg”,UriKind.Relative);
_capturedImage.CacheOption=BitmapCacheOption.OnLoad;
_capturedImage.EndInit();
}
公共ICommand captureMageCommand
{
获取{return\u captureImageCommand;}
}
公众形象
{
获取{return!dataModel.IsScriptRunning&!\u captureInProgress;}
}
公共图书馆正在进行中
{
获取{return\u captureInProgress;}
设置
{
if(_captureInProgress!=值)
{
_captureInProgress=值;
关于财产变更(“IsCaptureInProgress”);
OnPropertyChanged(“CanCaptureImage”);
}
}
}
公共整数百分比已完成
{
获取{return\u percentDone;}
设置
{
如果(_percentDone!=值)
{
_完成百分比=数值;
OnPropertyChanged(“完成百分比”);
}
}
}
公共位图图像捕获图像
{
获取{return\u capturedImage;}
}
私有void DataModelOnPropertyChanged(对象发送方,PropertyChangedEventArgs PropertyChangedEventArgs)
{
字符串属性=propertyChangedEventArgs.PropertyName;
如果(属性==“IsScriptRunning”)
{
OnPropertyChanged(“CanCaptureImage”);
}
已更改的不动产(不动产);
}
私有void captureImage(对象参数)
{
IsCaptureInProgress=true;
完成百分比=0;
//TODO:删除此占位符。
新的伪造图像捕获(本);
//待办事项(!)
}
内部无效捕获完成()
{
IsCaptureInProgress=false;
}
//当我们可以拍摄图像时,请删除此占位符。
私有类FakeImageCapture
{
CameraControlViewModel\u viewModel;
整数计数;
定时器_Timer=新定时器();
公共FakeImageCapture(CameraControlViewModel viewModel)
{
这是。_viewModel=viewModel;
_时间间隔=50;
_timer.appeated+=TimerOnTick;
_timer.Start();
}
私有void TimerOnTick(对象发送方,EventArgs EventArgs)
{
++_计数;
如果(_count而不是使用单独的IsEnabled绑定来启用/禁用按钮,那么实际上应该只使用RelayCommand的CanExecute谓词: 这将确保在调用CommandManager.InvalidateRequestSuggested()时正确启用/禁用该按钮。删除CanCaptureImage属性并按如下方式修改代码:
public CameraControlViewModel( DataModel dataModel )
: base( dataModel )
{
dataModel.PropertyChanged += DataModelOnPropertyChanged;
_captureImageCommand = new RelayCommand( captureImage, captureImage_CanExecute );
_capturedImage = new BitmapImage();
_capturedImage.BeginInit();
_capturedImage.UriSource = new Uri( "Images/fingerprint.jpg", UriKind.Relative );
_capturedImage.CacheOption = BitmapCacheOption.OnLoad;
_capturedImage.EndInit();
}
private bool captureImage_CanExecute( object arg)
{
return !dataModel.IsScriptRunning && !_captureInProgress;
}
您确定脚本没有继续运行吗?当然,@ernodeweard。当您在CanCaptureImage获取程序上设置断点时,是否在捕获完成后对其进行评估?必须向UI发出信号,要求重新评估CanCaptureImage…也许您可以尝试在中引发CaptureImageCommand的ICommand.CanExecuteChanged事件更改值后,IsCaptureInProgress属性设置器将被禁用。@ErnodeWeerd是的,该属性的计算正确。但直到我单击其他位置后,按钮才刷新。我认为这可能与按钮样式有关,但我关闭了所有设置,默认的视觉效果仍会出现这种情况。我认为这是使事情正常工作的原因。我添加了canExecute谓词,并返回CanCaptureImage。六个,六个。谢谢!
public CameraControlViewModel( DataModel dataModel )
: base( dataModel )
{
dataModel.PropertyChanged += DataModelOnPropertyChanged;
_captureImageCommand = new RelayCommand( captureImage, captureImage_CanExecute );
_capturedImage = new BitmapImage();
_capturedImage.BeginInit();
_capturedImage.UriSource = new Uri( "Images/fingerprint.jpg", UriKind.Relative );
_capturedImage.CacheOption = BitmapCacheOption.OnLoad;
_capturedImage.EndInit();
}
private bool captureImage_CanExecute( object arg)
{
return !dataModel.IsScriptRunning && !_captureInProgress;
}