在WPF中更改光标有时可以起作用,有时不起作用

在我的几个用户控件上,我通过使用改变光标

this.Cursor = Cursors.Wait; 

当我点击一些东西。

现在我想在button点击的WPF页面上做同样的事情。 当我将鼠标hover在我的button上时,光标变成一只手,但是当我点击它时,它不会更改为等待光标。 我想知道这是否与事实,这是一个button,或因为这是一个页面,而不是一个用户控件? 这似乎很奇怪的行为。

你是否需要将光标作为一个“等待”光标,只有当它超过特定的页面/用户控件? 如果没有,我build议使用Mouse.OverrideCursor :

 Mouse.OverrideCursor = Cursors.Wait; try { // do stuff } finally { Mouse.OverrideCursor = null; } 

这覆盖了你的应用程序的光标,而不仅仅是它的UI的一部分,所以你描述的问题消失了。

我们在应用程序中执行此操作的一种方法是使用IDisposable,然后using(){}块来确保光标在完成时被重置。

 public class OverrideCursor : IDisposable { public OverrideCursor(Cursor changeToCursor) { Mouse.OverrideCursor = changeToCursor; } #region IDisposable Members public void Dispose() { Mouse.OverrideCursor = null; } #endregion } 

然后在你的代码中:

 using (OverrideCursor cursor = new OverrideCursor(Cursors.Wait)) { // Do work... } 

覆盖将在以下两种情况下结束:达到使用语句的结尾或; 如果抛出exception,并且控制在语句结束之前离开语句块。

更新

为了防止光标闪烁,你可以这样做:

 public class OverrideCursor : IDisposable { static Stack<Cursor> s_Stack = new Stack<Cursor>(); public OverrideCursor(Cursor changeToCursor) { s_Stack.Push(changeToCursor); if (Mouse.OverrideCursor != changeToCursor) Mouse.OverrideCursor = changeToCursor; } public void Dispose() { s_Stack.Pop(); Cursor cursor = s_Stack.Count > 0 ? s_Stack.Peek() : null; if (cursor != Mouse.OverrideCursor) Mouse.OverrideCursor = cursor; } } 

您可以在button上使用数据触发器(使用视图模型)启用等待光标。

 <Button x:Name="NextButton" Content="Go" Command="{Binding GoCommand }"> <Button.Style> <Style TargetType="{x:Type Button}"> <Setter Property="Cursor" Value="Arrow"/> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsWorking}" Value="True"> <Setter Property="Cursor" Value="Wait"/> </DataTrigger> </Style.Triggers> </Style> </Button.Style> </Button> 

这是来自视图模型的代码:

 public class MainViewModel : ViewModelBase { // most code removed for this example public MainViewModel() { GoCommand = new DelegateCommand<object>(OnGoCommand, CanGoCommand); } // flag used by data binding trigger private bool _isWorking = false; public bool IsWorking { get { return _isWorking; } set { _isWorking = value; OnPropertyChanged("IsWorking"); } } // button click event gets processed here public ICommand GoCommand { get; private set; } private void OnGoCommand(object obj) { if ( _selectedCustomer != null ) { // wait cursor ON IsWorking = true; _ds = OrdersManager.LoadToDataSet(_selectedCustomer.ID); OnPropertyChanged("GridData"); // wait cursor off IsWorking = false; } } } 

如果你的应用程序使用asynchronous的东西,而你正在用鼠标的光标摆弄,你可能只想在主UI线程中做到这一点。 你可以使用应用程序的Dispatcher线程:

 Application.Current.Dispatcher.Invoke(() => { // The check is required to prevent cursor flickering if (Mouse.OverrideCursor != cursor) Mouse.OverrideCursor = cursor; });