Иногда меняет курсор в WPF, иногда
В нескольких моих usercontrols я меняю курсор, используя
this.Cursor = Cursors.Wait;
когда я нажимаю на что-то.
Теперь я хочу сделать то же самое на странице WPF при нажатии кнопки. Когда я наводил курсор на мою кнопку, курсор меняется на руку, но когда я нажимаю на нее, она не изменяется на курсор ожидания. Интересно, связано ли это с тем, что это кнопка, или потому что это страница, а не пользовательский контроль? Это похоже на странное поведение.
Ответы
Ответ 1
Вам нужен курсор, чтобы быть "ожидающим" курсором, только когда он над этой конкретной страницей /usercontrol? Если нет, я бы предложил использовать Mouse.OverrideCursor:
Mouse.OverrideCursor = Cursors.Wait;
try
{
// do stuff
}
finally
{
Mouse.OverrideCursor = null;
}
Это переопределяет курсор для вашего приложения, а не только для части его пользовательского интерфейса, поэтому проблема, которую вы описываете, уходит.
Ответ 2
Один из способов сделать это в нашем приложении - использовать IDisposable, а затем с блоками using(){}
, чтобы гарантировать, что курсор reset по завершении.
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...
}
Завершение завершится, когда либо: конец используемого оператора будет достигнут, либо; если исключение выбрано, и управление оставляет блок оператора до конца инструкции.
Обновление
Чтобы предотвратить мерцание курсора, вы можете:
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;
}
}
Ответ 3
Вы можете использовать триггер данных (с моделью просмотра) на кнопке, чтобы включить курсор ожидания.
<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>
Вот код из модели вида:
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;
}
}
}
Ответ 4
Если ваше приложение использует материал async и вы играете с курсором мыши, вы, вероятно, захотите сделать это только в основном потоке пользовательского интерфейса. Вы можете использовать поток приложения Dispatcher для этого:
Application.Current.Dispatcher.Invoke(() =>
{
// The check is required to prevent cursor flickering
if (Mouse.OverrideCursor != cursor)
Mouse.OverrideCursor = cursor;
});