【问题标题】:Show loading window显示加载窗口
【发布时间】:2012-11-29 22:08:57
【问题描述】:

我在 WPF 中的应用程序加载外部资源,所以我想在程序加载时显示加载表单。

我尝试创建表单,并在加载代码之前显示,并在加载结束时关闭。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
     LoadForm lf = new LoadForm();
     lf.Visibility = Visibility.Visible;

     // Al code that delays application loading

     lf.Close();
}

但我唯一得到的是加载进度完成并立即关闭时显示表单。

我认为我需要使用 System.Threading 但不确定。

谢谢。

注意我在 Window_Loaded() 方法中加载所有应用程序外部资源,而不是在主类方法中。

【问题讨论】:

  • 当您考虑线程时,我认为您走在正确的道路上。您应该打开您的表单,并将所有内容加载到不同的线程中。这样您的应用程序就会响应,并且不会锁定 UI。
  • 闪屏怎么样?这行得通吗?

标签: c# .net wpf window loading


【解决方案1】:

您应该查看有关在 WPF 中创建 SplashScreen 的 MSDN 文章。本质上,您将要显示的图像添加到项目中,并将 Build Action 设置为 SplashScreen,它将在程序启动时显示,并在显示主应用程序窗口时消失。


您也可以尝试导入 System.ComponentModel 类并使用 BackgroundWorker 来显示您的加载表单,它可以让您保持 UI 的响应能力。

public partial class MainWindow : Window
{
    Window1 splash;
    BackgroundWorker bg;
    public MainWindow()
    {

        InitializeComponent();

        bg = new BackgroundWorker();
        bg.DoWork += new DoWorkEventHandler(bg_DoWork);
        bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);

    }

    void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        splash.Hide();
    }

    void bg_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Threading.Thread.Sleep(10000);
    }


    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        splash = new Window1();
        splash.Show();
        bg.RunWorkerAsync();
    }
}

【讨论】:

  • 谢谢,但首先我有一个窗口可以输入用户名和密码(加载速度很快),然后,当在程序中验证时,所有的东西都会被加载,但这对我的其他项目很有用没有启动窗口。
  • @SteelersMan 看看我对使用BackgroundWorker 的编辑是否有帮助
  • 谢谢,这对我尝试做的非常有用,你帮助了两次。非常感谢:)
  • @SteelersMan 欢迎您,很高兴它有所帮助。如果其中一个答案回答了您的问题,您应该点击复选标记将您的问题标记为已回答。
  • @SteelersMan 只是为了记录,我没有提示您选择我的答案,只是回答了您的问题的答案。虽然很感激:)
【解决方案2】:

您应该将耗时的代码放在后台线程中(为此您可以使用 BackgroundWorker、Task 或 Async Await,具体取决于您的 dot net 框架版本)

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    LoadForm lf = new LoadForm();
    lf.Visibility = Visibility.Visible;
    //start the time consuming task in another thread
}


HeavyTaskCompleteEvent()
{
     lf.Close();
}

还要寻找显示加载屏幕的最佳方式。您也可以在主窗口中显示一些动画。我不认为显示表格是最好的方法。

【讨论】:

    【解决方案3】:

    我不久前制作了一个加载器类,您可以使用它。它在执行加载方法时显示一个窗口,完成后将其关闭并为您提供方法的输出:

    public class Loader<TActionResult>:FrameworkElement
    {
        private Func<TActionResult> _execute;
        public TActionResult Result { get; private set; }
        public delegate void OnJobFinished(object sender, TActionResult result);
        public event OnJobFinished JobFinished;
    
        public Loader(Func<TActionResult> execute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
    
            _execute = execute;
        }
    
        private Window GetWaitWindow()
        {
            Window waitWindow = new Window { Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None };
            waitWindow.Content = new TextBlock { Text = "Please Wait", FontSize = 30, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
    
            return waitWindow;
        }
    
        public void Load(Window waitWindow = null)
        {
            if (waitWindow == null)
            {
                waitWindow = GetWaitWindow();
            }
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += delegate
            {
                Dispatcher.BeginInvoke(new Action(delegate { waitWindow.ShowDialog(); }));
                Result = _execute();
                Dispatcher.BeginInvoke(new Action(delegate() { waitWindow.Close(); }));
            };
            worker.RunWorkerCompleted += delegate
            {
                worker.Dispose();
                if (JobFinished != null)
                {
                    JobFinished(this, Result);
                }
            };
            worker.RunWorkerAsync();
        }
    }
    

    使用方法:

    Loader<TResult> loader = new Loader<TResult>(MethodName);
    loader.JobFinished += new Loader<TResult>.OnJobFinished(loader_JobFinished);
    loader.Load();
    
    void loader_JobFinished(object sender, TResult result)
    {
        // do whatever you want with your result here
    }
    

    【讨论】:

    • 如何将参数传递给 MethodName 方法?
    猜你喜欢
    • 2015-07-19
    • 2021-11-29
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多