2012-01-03 129 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