2008-11-20 51 views
103

在我的幾個用戶控件,我用更改在WPF光標有時工作,有時不

this.Cursor = Cursors.Wait; 

改變光標當我點擊的東西。

現在我想在按鈕點擊的WPF頁面上做同樣的事情。當我將鼠標懸停在我的按鈕上時,光標變成一隻手,但是當我點擊它時,它不會更改爲等待光標。我想知道這是否與這是一個按鈕的事實有關,或者因爲這是一個頁面而不是用戶控件?這似乎很奇怪的行爲。

回答

176

只有當光標位於特定頁面/ usercontrol上時,是否需要將光標作爲「等待」光標?如果沒有,我建議使用Mouse.OverrideCursor

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

這將覆蓋光標爲您的應用程序,而不是隻爲它的用戶界面的一部分,所以您所描述的問題消失。

+0

我自己[答案]類似(http://stackoverflow.com/a/8211178/448232),日期在3年後(幾乎完全!)。我喜歡這個問題的答案,但最簡單的一個總是最誘人的:) – 2012-07-31 13:58:42

+0

這個解決方案將光標變成一個「等待」光標,但它不會禁用任何進一步的鼠標輸入。我嘗試過使用這個解決方案,雖然鼠標變成了等待遊標,但我仍然可以單擊我的WPF應用程序中的任何UI元素,沒有任何問題。任何想法如何阻止用戶在等待遊標期間實際使用鼠標是否處於活動狀態? – 2012-12-04 14:46:30

+1

舊的和現在被接受的,這不是正確的答案。覆蓋應用程序的光標不同於覆蓋控制光標(第二個在WPF中有問題)。覆蓋應用程序遊標可能會產生令人討厭的副作用,例如,彈出式(錯誤)消息框可能會被迫錯誤地使用相同的重寫遊標,而意圖只能在鼠標懸停在實際和主動控件上時進行覆蓋。 – 2014-06-06 18:48:33

57

我們在應用程序中執行此操作的一種方法是使用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; 
    } 

} 
36

您可以在按鈕上使用數據觸發(與視圖模型),以使等待光標。

<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

如果應用程序使用異步的東西,你用鼠標的光標擺弄,您可能想這樣做只能在主UI線程。您可以使用應用程序的線程調度爲:

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