在WPF中更改光标有时会起作用,有时则不然

时间:2008-11-20 21:57:18

标签: c# wpf

在我的几个用户控件上,我使用

更改了光标
this.Cursor = Cursors.Wait;

当我点击某些东西时。

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

5 个答案:

答案 0 :(得分:191)

只有当光标位于特定页面/ usercontrol上时,您是否需要将光标作为“等待”光标?如果没有,我建议使用Mouse.OverrideCursor

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

这会覆盖应用程序的光标,而不仅仅是其UI的一部分,因此您描述的问题就会消失。

答案 1 :(得分:59)

我们在应用程序中执行此操作的一种方法是使用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...
}

当以下任何一个结束时,覆盖将结束:到达using语句的结尾或;如果抛出异常并且控制在语句结束之前离开语句块。

<强>更新

为防止光标闪烁,您可以执行以下操作:

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;
  }

}

答案 2 :(得分:36)

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

<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;
      }
   }
}

答案 3 :(得分:6)

如果您的应用程序使用异步内容并且您正在摆弄鼠标光标,那么您可能只想在主UI线程中执行此操作。你可以使用app的Dispatcher线程:

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

答案 4 :(得分:0)

以下内容对我有用:

ForceCursor = true;
Cursor = Cursors.Wait;