代码之家  ›  专栏  ›  技术社区  ›  Philipp Schmid

WPF启动屏幕,如Blend

  •  1
  • Philipp Schmid  · 技术社区  · 15 年前

    我们的主WPF窗口(“主窗口”)需要相当长的时间来创建(它使用类似于Visual Studio的功能区和停靠面板)。就像在混合 第一行动 将永远是 选择要处理的现有项目或创建新项目 . 因此,我们希望尽快显示这个“选择项目”窗口,并在后台创建沉重的“主窗口”(在用户单击“选择项目”窗口上的“确定”之前不可见)。

    最好使用两个WPF窗口(一个用于项目选择,一个用于主控件)来构建这个启动场景,最好的方法是什么?

    我知道 this sample 它演示了如何在应用程序启动后不久加载win32窗口,但我更喜欢只使用wpf的解决方案。

    另一个可能的解决方案是 multiple WPF UI threads 但是,生命周期管理和窗口到窗口通信是非常重要的。

    问题:

    我能看看吗 实现2 wpf窗口解决方案时启动时间更快 与简单地创建“主窗口”而不实现“选择项目”窗口相比(假设我可以找到一个处理窗口生命周期的实现)?

    应该 在主应用程序线程上创建“选择项目”窗口 后台线程上的“主窗口”(或反之亦然)?

    如果我需要使用win32启动窗口来提高速度, 我怎么沟通 用户对项目名称的选择 到主WPF应用程序窗口 ?

    有人知道怎么做吗 实际上,Blend实现了它们的启动窗口 (我想在这里模仿哪个)?

    任何实现指针都将非常感谢!

    2 回复  |  直到 13 年前
        1
  •  1
  •   Ray Burns    15 年前

    构建此方案的最佳方法

    我会:

    1. 创建类来管理“选择项目”窗口的数据(如MRU列表、模板等),确保它们是独立的,不需要与主线程交互。

    2. 在应用程序对象或单例对象中存储有关“当前”项目的信息。

    3. 创建“选择项目”窗口以完全独立于主窗口运行。

    4. 设置“选择项目”窗口的“打开”和“创建”按钮以启动 Application.Open 命令,并将按钮上的commandParameter绑定到包含要打开的文件名(或要实例化的模板)的属性。

    5. 添加一个 CommandBinding 对于 应用程序。打开 命令在窗口级别获取命令参数并在应用程序对象中设置当前项目。

    6. 在应用程序的启动代码中,立即生成一个线程以创建“选择项目”窗口,然后立即执行分派器。在applicationIdle优先级下调用,然后调用一个非常短的线程。休眠几次,然后继续,允许创建主窗口,但使其最初不可见。

    7. 在主窗口中设置触发器,使其在第一次设置当前项目后可见。

    以下是如何 Open “选择项目”窗口中的命令处理程序可能会更新应用程序对象中的项目路径:

    Application.Current.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() =>
    {
      ((App)Application.Current).CurrentProjectPath = e.Parameter;
    }
    

    应用程序的启动代码如下所示:

    public override void OnStartup(StartupEventArgs e)
    {
      new Thread(() => { new SelectProject().Show(); }).Start();
      for(int i=0; i<10; i++)
      {
        Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, () => {});
        Thread.Sleep(20);
      }
      _guts = new MainWindowContent(); // probably a UserControl
      _guts.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
      _guts.Arrange(new Rect(0, 0, guts.DesiredSize.Width, guts.DesiredSize.Height));
      _guts.SetBinding(VisibilityProperty,
        new Binding { Source = this, Path="StartupFinished",
                      Converter = BoolToVisibiltyConverter.Instance });
    
      _mainWindow = new MainWindow { Content = guts };
      // Note: Title and other properties of MainWindow would be set in the XAML
    }
    

    注意额外的代码,以确保内脏得到测量和提前安排。

    下面是设置当前项目路径的代码:

    public string CurrentProjectPath
    {
      get { return _currentProjectPath; }
      set
      {
        _currentProjectPath = value;
        LoadProject();
        _startupFinished = true;
        OnPropertyChanged("StartupFinished");
      }
    }
    

    此代码假定XAML绑定主窗口的可见性属性

    StartupFinished是主窗口的Visibility属性绑定到的DependencyProperty,但可以通过其他方式完成。

    这样你能看到更快的启动时间吗?

    对。

    应选择在主线程和其他线程上创建项目,反之亦然

    您应该在主线程上创建MainWindow,以便它与应用程序对象共享相同的调度程序。这意味着“选择项目”必须在第二个线程中。

    如果需要使用win32启动窗口来提高速度

    这可能不是必要的。WPF本身的启动只是一秒钟的一小部分。但如果必要的话, Application.Current.Dispatcher.Invoke 上面描述的技术将起作用。

    你知道Blend如何实现它的启动窗口吗?

        2
  •  0
  •   Louis S. Berman    13 年前

    你有一个我可以看的完整的工作轴吗?我试着从上面所附的代码片段中找出一些东西,但无法得到一个示例来工作…