una quitar poner normal manita imagen cursores como cambiar animado wpf mvvm cursor wait

wpf - quitar - cursor animado



MVVM Wait Cursor ¿cómo configurar el cursor de espera durante la invocación de un comando? (7)

El ViewModel solo debe decidir si está ocupado, y la decisión sobre qué cursor usar, o si usar alguna otra técnica, como una barra de progreso, debe dejarse en la vista.

Y, por otro lado, tampoco es deseable manejarlo con código subyacente en la Vista, porque lo ideal es que las Vistas no tengan código subyacente.

Por lo tanto, elegí hacer una clase que se pueda usar en View XAML para especificar que el cursor debería cambiarse a Wait cuando el ViewModel está ocupado. Usando UWP + Prism la definición de clase es:

public class CursorBusy : FrameworkElement { private static CoreCursor _arrow = new CoreCursor(CoreCursorType.Arrow, 0); private static CoreCursor _wait = new CoreCursor(CoreCursorType.Wait, 0); public static readonly DependencyProperty IsWaitCursorProperty = DependencyProperty.Register( "IsWaitCursor", typeof(bool), typeof(CursorBusy), new PropertyMetadata(false, OnIsWaitCursorChanged) ); public bool IsWaitCursor { get { return (bool)GetValue(IsWaitCursorProperty); } set { SetValue(IsWaitCursorProperty, value); } } private static void OnIsWaitCursorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { CursorBusy cb = (CursorBusy)d; Window.Current.CoreWindow.PointerCursor = (bool)e.NewValue ? _wait : _arrow; } }

Y la forma de usarlo es:

<mvvm:SessionStateAwarePage x:Class="Orsa.Views.ImportPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mvvm="using:Prism.Windows.Mvvm" xmlns:local="using:Orsa" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mvvm:ViewModelLocator.AutoWireViewModel="True" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <Grid.RowDefinitions> . . </Grid.RowDefinitions> <local:CursorBusy IsWaitCursor="{Binding IsBusy}"/> (other UI Elements) . . </Grid> </mvvm:SessionStateAwarePage>

Escenario: el usuario hace clic en un botón en la Vista. Esto invoca un comando en el Modelo de Vista, DoProcessing How, y dónde se establece el cursor de Espera, considerando las responsabilidades de la Vista y el Modelo de Vista.

Para que quede claro, solo estoy buscando cambiar el cursor de DEFAULT a un reloj de arena mientras se ejecuta el comando. Cuando se completa el comando, el cursor cambia de nuevo a una flecha. (Lo que estoy buscando es una operación sincrónica y quiero bloquear la interfaz de usuario).

He creado una propiedad IsBusy en el ViewModel. ¿Cómo me aseguro de que el puntero del mouse de la aplicación cambie?


El comando se maneja en el modelo de vista, por lo que la decisión razonable sería hacer lo siguiente:

1) Cree un servicio de indicador de ocupado e inyectarlo en el modelo de vista (esto le permitirá reemplazar la lógica del cursor con alguna animación desagradable fácilmente)

2) En el controlador de comandos, llame al servicio de indicador de ocupado para notificar al usuario

Puede que me equivoque, pero parece que está intentando hacer algunos cálculos pesados ​​o E / S en el hilo de la interfaz de usuario. Le recomiendo encarecidamente que realice un trabajo en el grupo de subprocesos en este caso. Puede usar Task y TaskFactory para ajustar fácilmente el trabajo con ThreadPool


En mi opinión, está perfectamente bien que la lógica del cursor de espera esté al lado del comando en el modelo de vista.

En cuanto a la mejor manera de cambiar el cursor, cree un envoltorio IDisposable que cambie la propiedad Mouse.OverrideCursor .

public class StackedCursorOverride : IDisposable { private readonly static Stack<Cursor> CursorStack; static StackedCursorOverride() { CursorStack = new Stack<Cursor>(); } public StackedCursorOverride(Cursor cursor) { CursorStack.Push(cursor); Mouse.OverrideCursor = cursor; } public void Dispose() { var previousCursor = CursorStack.Pop(); if (CursorStack.Count == 0) { Mouse.OverrideCursor = null; return; } // if next cursor is the same as the one we just popped, don''t change the override if ((CursorStack.Count > 0) && (CursorStack.Peek() != previousCursor)) Mouse.OverrideCursor = CursorStack.Peek(); } }

Uso:

using (new StackedCursorOverride(Cursors.Wait)) { // ... }

Lo anterior es una versión revisada de la solución que publiqué en esta question .


Hay una gran Session (a las 50:58) de Laurent Bugnion en línea (Creador de MVVM Light ). También hay una sesión de DeepDive disponible (alternativamente here (a las 24:47)).

En al menos uno de ellos, el código en vivo de un indicador de ocupado es un BusyProperty.


Lo estoy usando exitosamente en mi aplicación:

/// <summary> /// Contains helper methods for UI, so far just one for showing a waitcursor /// </summary> public static class UIServices { /// <summary> /// A value indicating whether the UI is currently busy /// </summary> private static bool IsBusy; /// <summary> /// Sets the busystate as busy. /// </summary> public static void SetBusyState() { SetBusyState(true); } /// <summary> /// Sets the busystate to busy or not busy. /// </summary> /// <param name="busy">if set to <c>true</c> the application is now busy.</param> private static void SetBusyState(bool busy) { if (busy != IsBusy) { IsBusy = busy; Mouse.OverrideCursor = busy ? Cursors.Wait : null; if (IsBusy) { new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, System.Windows.Application.Current.Dispatcher); } } } /// <summary> /// Handles the Tick event of the dispatcherTimer control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private static void dispatcherTimer_Tick(object sender, EventArgs e) { var dispatcherTimer = sender as DispatcherTimer; if (dispatcherTimer != null) { SetBusyState(false); dispatcherTimer.Stop(); } } }

Esto ha sido tomado de here . Courtsey huttelihut .

SetBusyState llamar al método SetBusyState cada vez que piense que va a realizar alguna operación que consuma tiempo. p.ej

... UIServices.SetBusyState(); DoProcessing(); ...

Esto cambiará automáticamente su cursor para esperar el cursor cuando la aplicación esté ocupada y volverá a la normalidad cuando esté inactivo.


Un método muy simple es simplemente enlazar a la propiedad ''Cursor'' de la ventana (o cualquier otro control). Por ejemplo:

XAML:

<Window x:Class="Example.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Cursor="{Binding Cursor}" />

Propiedad del cursor de ViewModel (usando Apex.MVVM):

private NotifyingProperty cursor = new NotifyingProperty("Cursor", typeof(System.Windows.Input.Cursor), System.Windows.Input.Cursors.Arrow); public System.Windows.Input.Cursor Cursor { get { return (System.Windows.Input.Cursor)GetValue(cursor); } set { SetValue(cursor, value); } }

Luego simplemente cambie el cursor en su vista cuando sea necesario ...

public void DoSomethingLongCommand() { Cursor = System.Windows.Input.Cursors.Wait; ... some long process ... Cursor = System.Windows.Input.Cursors.Arrow; }


private static void LoadWindow<T>(Window owner) where T : Window, new() { owner.Cursor = Cursors.Wait; new T { Owner = owner }.Show(); owner.Cursor = Cursors.Arrow; }