WPF 请稍候对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21734348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:49:42  来源:igfitidea点击:

WPF Please Wait Dialog

c#.netwpfwait

提问by goflo

I'm developing a WPF desktop application in c# 4.0 which has to handle a lot of long-running operations (loading data from the DB, calculating simulations, optimizing routes, etc.).

我正在用 c# 4.0 开发 WPF 桌面应用程序,它必须处理大量长时间运行的操作(从数据库加载数据、计算模拟、优化路线等)。

When these long-running operations run in the background I want to show a Please-Wait dialog. When the Please-Wait dialog is shown the application should be locked, but to just disable the application window isn't a good idea because all the DataGrids would lose their status (SelectedItem).

当这些长时间运行的操作在后台运行时,我想显示一个请等待对话框。当显示 Please-Wait 对话框时,应用程序应该被锁定,但是仅仅禁用应用程序窗口并不是一个好主意,因为所有的 DataGrids 都会失去它们的状态 ( SelectedItem)。

What I have so far works but there are some problems: A new WaitXUI is created using the Create-factory method. The Create method expects caption text and a refernce to the host control that should be locked. The Create method sets the StartupLocation of the window, the caption text and the host to lock:

到目前为止,我所做的工作是有效的,但存在一些问题:使用 Create-factory 方法创建了一个新的 WaitXUI。Create 方法需要标题文本和对应该锁定的宿主控件的引用。Create 方法将窗口的 StartupLocation、标题文本和主机设置为锁定:

WaitXUI wait = WaitXUI.Create("Simulation running...", this);
wait.ShowDialog(new Action(() =>
{
    // long running operation
}));

With the overloaded ShowDialog method the WaitXUI can then be displayed. The ShowDialog overload does expect an Action which wraps the long running operation.

使用重载的 ShowDialog 方法,可以显示 WaitXUI。ShowDialog 重载确实需要一个 Action 来包装长时间运行的操作。

In the ShowDialog overload I just start the Action in its own thread and then disable the host control (set Opacity to 0.5 and set IsEnabled to false) and call ShowDialog of the base class.

在 ShowDialog 重载中,我只是在它自己的线程中启动 Action,然后禁用主机控件(将 Opacity 设置为 0.5 并将 IsEnabled 设置为 false)并调用基类的 ShowDialog。

public bool? ShowDialog(Action action) 
    {
    bool? result = true;

    // start a new thread to start the submitted action
    Thread t = new Thread(new ThreadStart(delegate()
    {
        // start the submitted action
        try
        {
            Dispatcher.UnhandledException += Dispatcher_UnhandledException;
            Dispatcher.Invoke(DispatcherPriority.Normal, action);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            // close the window
            Dispatcher.UnhandledException -= Dispatcher_UnhandledException;
            this.DoClose();
        }
    }));
    t.Start();

    if (t.ThreadState != ThreadState.Stopped)
    {
        result = this.ShowDialog();
    }
    return result;
}

private new bool? ShowDialog() 
{
    DisableHost();
    this.Topmost = true;
    return base.ShowDialog();
}

private void DisableHost()
{
    if (host != null)
    {
        host.Dispatcher.Invoke(new Action(delegate()
        {
            this.Width = host.Width - 20;
            host.Cursor = Cursors.Wait;
            host.IsEnabled = false;
            host.Opacity = 0.5;
        }));
    }
}

Here are the problems with this:

以下是这方面的问题:

  • Disabling the host control results in lost of status information (SelectedItems...)
  • The WaitXUI sometimes is shown for only some milliseconds when the thread ends a few ms after the WaitXUI is shown
  • Sometimes the dialog doesn't appear at all although the thread is still running
  • 禁用主机控件会导致状态信息丢失(SelectedItems...)
  • 当线程在 WaitXUI 显示几毫秒后结束时,WaitXUI 有时仅显示几毫秒
  • 有时尽管线程仍在运行,但对话框根本不出现

These are the main problems which come to my mind at the moment. How can this concept be improved, or what other methods can be employed to address this problem?

这些是我目前想到的主要问题。如何改进这个概念,或者可以采用哪些其他方法来解决这个问题?

Thanks in advance!

提前致谢!

回答by Sheridan

A little lateral thinking always helps when developing WPF applications. You can fulfil your requirements easily with just a Grid, a Rectangle, a boolproperty (which you could already have) and a BooleanToVisibilityConverterand you won't have to disable any controls.

在开发 WPF 应用程序时,稍微横向思考总是有帮助的。您只需使用 a Grid、 a Rectanglebool属性(您可能已经拥有)和 a即可轻松满足您的要求,BooleanToVisibilityConverter而且您不必禁用任何控件。

The idea is simple. Add a white Rectanglein front of your view content with its Opacityproperty set between 0.5and around 0.75. Data bind its Visibilityproperty to the boolproperty in your view model or code behind and plug in the BooleanToVisibilityConverter:

这个想法很简单。Rectangle在您的视图内容前面添加一个白色,其Opacity属性设置为 between0.5和 around 0.75。数据将其Visibility属性绑定到bool您的视图模型或代码背后的属性并插入BooleanToVisibilityConverter

<Grid>
    <Grid>
        <!--Put your main content here-->
    </Grid>
    <Rectangle Fill="White" Opacity="0.7" Visibility="{Binding IsWaiting, 
        Converter={StaticResource BooleanToVisibilityConverter}}" />
    <!--You could add a 'Please Wait' TextBlock here-->
</Grid>

Now when you want to disable the controls, you just set the boolproperty to trueand the Rectanglewill make the UI appear faded:

现在,当您想禁用控件时,只需将bool属性设置为trueRectangle就会使 UI 看起来褪色:

IsWaiting = true;

回答by Eugene P.

Don't really need to create own implementation, I think it's redundant.

真的不需要创建自己的实现,我认为这是多余的。

take a look into already created component, like BusyIndicator, for similar needs. which is vital and effective. .

为了类似的需求,查看已经创建的组件,比如BusyIndi​​cator。这是至关重要和有效的。.

more info from codeplex

来自codeplex 的更多信息