2012-01-03 55 views
8

我有一個wpf應用程序,它執行非常繁重的操作,用戶在應用程序「認爲」時需要等待。「繁忙」效果覆蓋

我想要做的是,當應用程序的主線程正在考慮時,另一個線程將禁用整個窗口,並給它一種灰色的顏色,並在屏幕中間出現一個圓形的進度條。

這是一個很大的問題,我並不需要整個代碼來做這個只是一般的想法。

感謝您的幫助..

回答

2

卸載重行動,以一個新的線程,做在主線程的UI的東西(禁用,灰色出來,進度條)。請參閱BackgroundWorker and Dispatcher

使用一個新的線程爲UI的東西是可能的,但不使用現有的窗口。一個UI控件(Dispatcher)可以在線使用/調用它所屬的線程。然而,你可以創建一個新的線程,並使用一個新的窗口與一個新的分派器來做UI的東西。然後您必須將新窗口置於原始位置。不像我的第一個建議那麼容易。如果您不知道重執行何時執行,那麼這可能是一個選項。見hereherehere

+0

非常感謝你,這是非常有益的! – 2012-01-03 12:23:34

2

看看這個示例:

public void DoHeavyWork() 
    { 
     mainDispatcher = Dispatcher.CurrentDispatcher; 
     DisableWindow(); 
     workDelegate.BeginInvoke(EnableWindowCallBack, null); 
    } 

    private void EnableWindowCallBack(IAsyncResult asyncResult) 
    { 
     workDelegate.EndInvoke(asyncResult); 
     mainDispatcher.InvokeIfRequired(() => { EnableWindow(); }); 
    } 

當你調用DoHeavyWork我認爲我們是可以訪問的用戶界面,這應該是平常的線程上。 DisableWindow顯示動畫或任何工作時應顯示的內容。然後調用預定義的代理,workDelegate將在新線程上運行,並且完成後,回調應恢復該視圖。

請注意,EnableWindow的調用必須在有權訪問UI的線程上進行。

+0

非常感謝,這非常有幫助! – 2012-01-03 12:36:32

+0

很高興能有所幫助。您可以通過投票表明您的感謝,並接受其中一個答案作爲正確答案。 – 2012-01-31 18:21:59

12

除了上述建議(後臺工作人員,調度員) - 是的,這些是獲得你想要的正確技術,但讓我討論你在你的問題中請求的UI效果。如果您使用的是MVVM模式,則可以創建一些「我很忙」的UI並綁定到視圖模型中的IsBusy屬性以顯示和隱藏UI。例如:

public class MyViewModel : INotifyPropertyChanged 
{ 
    // Bind to this property any UI you want to 
    // show/hide during long running updates 
    public bool IsBusy 
    { 
     get { return _isBusy; } 
     set 
     { 
      _isBusy = true; 
      OnPropertyChanged("IsBusy"); 
     } 
    } 

    private void OnPropertyChanged(string prop) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(prop)); 
     } 
    } 

    // Note: This is intended to be called on a background thread 
    private void DoLongRunningOperationOnABackgroundThread() 
    { 
     try 
     { 
      IsBusy = true; 

      // do your work 
     } 
     finally 
     { 
      IsBusy = false; 
     } 
    } 
} 

然後在UI使用此XAML(或類似)

<UserControl:MyControl x:Class="MyApp.MyControl" 
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <UserControl.Resources> 
     <BooleanToVisibilityConverter x:Key="boolToVis"/> 
    </UserControl.Resources> 
    <Grid> 
     <!-- your UI code goes here --> 

     <!-- Below this, at higher Z-Order place a control to gray out the screen when IsBusy = true --> 
     <Border Background="#55000000" BorderThickness="0" Visibility="{Binding IsBusy, Converter={StaticResource boolToVis}}"> 
      <TextBlock Text="I AM BUSY!" Font-Size="32" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/> 
     </Border> 
    <Grid> 
</UserControl>  

當你使用一個後臺工作或線程池來調用DoLongRunningOperation功能在您的視圖模型的淨效應將是, Xaml中定義的邊界會在操作開始/停止時顯示/隱藏。當WPF爲你處理線程編組時,你不需要調度器在這裏調用。

在網上也有一些帶有旋轉動畫等的繁忙控件的實現,它們也不適合用戶界面。

最好的問候,

+0

謝謝,我在網上發現了一些很酷的動畫實現,謝謝了很多 – 2012-01-03 12:24:21

+0

沒有probs :)請注意,您可以使用WPF Grid將控件直接放在另一個控件上(Z指數更高)。這對於您正在尋找的灰色效果非常有用。 – 2012-01-03 12:31:29