Cambiare il cursore in WPF a volte funziona, a volte no

Su molti dei miei controlli utente, cambio il cursore usando

this.Cursor = Cursors.Wait; 

quando clicco su qualcosa.

Ora voglio fare la stessa cosa su una pagina WPF con un clic del pulsante. Quando passo il mouse sopra il mio pulsante, il cursore si trasforma in una mano, ma quando faccio clic, non cambia il cursore di attesa. Mi chiedo se questo abbia qualcosa a che fare con il fatto che si tratta di un pulsante, o perché si tratta di una pagina e non di un controllo elettronico? Sembra un comportamento strano.

Hai bisogno che il cursore sia un cursore “wait” solo quando è finito su quella particolare pagina / usercontrol? In caso contrario, suggerirei di utilizzare Mouse.OverrideCursor :

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

Questo sovrascrive il cursore per l’applicazione piuttosto che solo per una parte della sua interfaccia utente, quindi il problema che stai descrivendo scompare.

Un modo in cui lo facciamo nella nostra applicazione è l’utilizzo di IDisposable e quindi con using(){} blocks per garantire che il cursore venga ripristinato al termine.

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

e poi nel tuo codice:

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

L’override terminerà quando: la fine dell’istruzione using viene raggiunta o; se viene lanciata un’eccezione e il controllo lascia il blocco dell’istruzione prima della fine dell’istruzione.

Aggiornare

Per evitare lo sfarfallio del cursore puoi fare:

 public class OverrideCursor : IDisposable { static Stack s_Stack = new Stack(); 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; } } 

È ansible utilizzare un trigger di dati (con un modello di visualizzazione) sul pulsante per abilitare un cursore di attesa.

  

Ecco il codice dal modello di visualizzazione:

 public class MainViewModel : ViewModelBase { // most code removed for this example public MainViewModel() { GoCommand = new DelegateCommand(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; } } } 

Se la tua applicazione utilizza elementi asincroni e stai armeggiando con il cursore del mouse, probabilmente lo vuoi fare solo nel thread principale dell’interfaccia utente. Puoi utilizzare il thread Dispatcher dell’app per:

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