Изменение курсора в WPF иногда работает, иногда нет - PullRequest
113 голосов
/ 21 ноября 2008

В некоторых моих пользовательских элементах управления я меняю курсор с помощью

this.Cursor = Cursors.Wait;

когда я что-то нажимаю.

Теперь я хочу сделать то же самое на странице WPF одним нажатием кнопки. При наведении курсора на кнопку курсор превращается в руку, но при нажатии на нее он не меняется на курсор ожидания. Интересно, это как-то связано с тем, что это кнопка, или это страница, а не пользовательский контроль? Это кажется странным поведением.

Ответы [ 4 ]

192 голосов
/ 21 ноября 2008

Вам нужен курсор, чтобы он был «ждущим», только когда он находится над этой конкретной страницей / usercontrol? Если нет, я бы предложил использовать Mouse.OverrideCursor :

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

Это переопределяет курсор для вашего приложения, а не только для части его пользовательского интерфейса, поэтому описываемая вами проблема исчезает.

59 голосов
/ 24 марта 2009

Один из способов сделать это в нашем приложении - использовать 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;
  }

}
36 голосов
/ 18 мая 2010

Для включения курсора ожидания можно использовать триггер данных (с моделью представления) на кнопке.

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

Вот код из view-модели:

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;
      }
   }
}
6 голосов
/ 08 июля 2013

Если ваше приложение использует асинхронный контент и вы манипулируете курсором мыши, вы, вероятно, захотите сделать это только в основном потоке пользовательского интерфейса. Для этого вы можете использовать ветку Dispatcher приложения:

Application.Current.Dispatcher.Invoke(() =>
{
    // The check is required to prevent cursor flickering
    if (Mouse.OverrideCursor != cursor)
        Mouse.OverrideCursor = cursor;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...