Changing the cursor in WPF sometimes works, sometimes doesn't

后端 未结 5 602
[愿得一人]
[愿得一人] 2020-11-28 23:08

On several of my usercontrols, I change the cursor by using

this.Cursor = Cursors.Wait;

when I click on something.

Now I want to do

相关标签:
5条回答
  • 2020-11-28 23:30

    If your application uses async stuff and you're fiddling with Mouse's cursor, you probably want to do it only in main UI thread. You can use app's Dispatcher thread for that:

    Application.Current.Dispatcher.Invoke(() =>
    {
        // The check is required to prevent cursor flickering
        if (Mouse.OverrideCursor != cursor)
            Mouse.OverrideCursor = cursor;
    });
    
    0 讨论(0)
  • 2020-11-28 23:37

    The following worked for me:

    ForceCursor = true;
    Cursor = Cursors.Wait;
    
    0 讨论(0)
  • 2020-11-28 23:40

    One way we do this in our application is using IDisposable and then with using(){} blocks to ensure the cursor is reset when done.

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

    and then in your code:

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

    The override will end when either: the end of the using statement is reached or; if an exception is thrown and control leaves the statement block before the end of the statement.

    Update

    To prevent the cursor flickering you can do:

    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;
      }
    
    }
    
    0 讨论(0)
  • 2020-11-28 23:40

    You can use a data trigger (with a view model) on the button to enable a wait cursor.

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

    Here is the code from the view-model:

    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;
          }
       }
    }
    
    0 讨论(0)
  • 2020-11-28 23:45

    Do you need the cursor to be a "wait" cursor only when it's over that particular page/usercontrol? If not, I'd suggest using Mouse.OverrideCursor:

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

    This overrides the cursor for your application rather than just for a part of its UI, so the problem you're describing goes away.

    0 讨论(0)
提交回复
热议问题