Sur plusieurs de mes contrôles utilisateur, je change de curseur en utilisant
this.Cursor = Cursors.Wait;
quand je clique sur quelque chose.
Maintenant, je veux faire la même chose sur une page WPF sur un clic de bouton. Lorsque je survole mon bouton, le curseur se transforme en une main, mais lorsque je clique dessus, le curseur d’attente ne se modifie pas. Je me demande si cela a quelque chose à voir avec le fait qu'il s'agisse d'un bouton ou s'il s'agit d'une page et non d'un contrôle utilisateur? Cela ressemble à un comportement étrange.
Avez-vous besoin que le curseur soit un curseur "attendre" uniquement lorsqu'il se trouve au-dessus de cette page/commande utilisateur? Sinon, je suggérerais d'utiliser Mouse.OverrideCursor :
Mouse.OverrideCursor = Cursors.Wait;
try
{
// do stuff
}
finally
{
Mouse.OverrideCursor = null;
}
Cela remplace le curseur pour votre application plutôt que seulement pour une partie de son interface utilisateur. Le problème que vous décrivez disparaît donc.
Pour ce faire, notre application utilise IDisposable, puis des blocs using(){}
pour s'assurer que le curseur est réinitialisé une fois l'opération terminée.
public class OverrideCursor : IDisposable
{
public OverrideCursor(Cursor changeToCursor)
{
Mouse.OverrideCursor = changeToCursor;
}
#region IDisposable Members
public void Dispose()
{
Mouse.OverrideCursor = null;
}
#endregion
}
et ensuite dans votre code:
using (OverrideCursor cursor = new OverrideCursor(Cursors.Wait))
{
// Do work...
}
La substitution prend fin lorsque: la fin de l'instruction using est atteinte ou; si une exception est levée et que le contrôle quitte le bloc d'instructions avant la fin de l'instruction.
Mise à jour
Pour empêcher le curseur de scintiller, vous pouvez effectuer les opérations suivantes:
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;
}
}
Vous pouvez utiliser un déclencheur de données (avec un modèle de vue) sur le bouton pour activer un curseur d'attente.
<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>
Voici le code du modèle de vue:
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;
}
}
}
Si votre application utilise des éléments asynchrones et que vous manipulez le curseur de la souris, vous souhaiterez probablement le faire uniquement dans le fil principal de l'interface utilisateur. Vous pouvez utiliser le fil de discussion de l'application pour cela:
Application.Current.Dispatcher.Invoke(() =>
{
// The check is required to prevent cursor flickering
if (Mouse.OverrideCursor != cursor)
Mouse.OverrideCursor = cursor;
});