在 WPF 中更改光标有时有效,有时无效

在我的几个用户控件上,我使用

this.Cursor = Cursors.Wait;

当我点击什么的时候。

现在我想做同样的事情在 WPF 页面上的按钮点击。当我将鼠标悬停在按钮上时,光标会变成一只手,但当我单击它时,它不会变成等待光标。我想知道这是否与它是一个按钮这一事实有关,或者因为它是一个页面而不是一个用户控件?这看起来很奇怪。

127368 次浏览

只有当光标位于特定的页面/用户控件上时,才需要将光标设置为“等待”光标吗?如果没有,我建议使用 鼠标,覆盖光标:

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

这将覆盖应用程序的光标,而不仅仅覆盖其 UI 的一部分,因此您所描述的问题将不复存在。

我们在应用程序中这样做的一种方法是使用 IDisposable,然后使用 using(){}块,以确保完成后光标被重置。

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

重写将在以下两种情况下结束: 到达 using 语句的结束时; 或者,如果抛出异常并且控制在语句结束前离开语句块。

更新

要防止光标闪烁,您可以这样做:

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


}

您可以在按钮上使用数据触发器(带有视图模型)来启用等待游标。

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

如果您的应用程序使用了异步的东西,并且您正在摆弄 Mouse 的光标,那么您可能希望只在主 UI 线程中进行操作。你可以使用应用程序的 Dispatcher 线程:

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

以下几点对我很有效:

ForceCursor = true;
Cursor = Cursors.Wait;