Лучший способ построить этот сценарий
Я бы:
Создайте классы для управления данными для вашего окна «Выбор проекта» (например, списки MRU, шаблоны и т. Д.), Убедившись, что они автономны и не требуют взаимодействия с основным потоком.
Хранить информацию о «текущем» проекте (ах) в объекте Application или в одноэлементном объекте.
Создайте окно «Выбор проекта», чтобы работать полностью независимо от главного окна.
Установите кнопки «Открыть» и «Создать» в окне «Выбор проекта» для запуска команды Application.Open
и привяжите параметр CommandParameter к кнопке со свойством, которое содержит имя файла для открытия (или шаблон для экземпляр).
Добавьте CommandBinding
для команды Application.Open
на уровне окна, чтобы принять параметр команды и установить текущий проект в объекте приложения.
В коде запуска вашего приложения немедленно создайте поток, чтобы создать окно «Выбор проекта», затем сразу выполните {Dispatcher.Invoke с приоритетом ApplicationIdle, а затем несколько раз очень короткий Thread.Sleep}, затем продолжите , позволяя создать главное окно, но сделав его изначально невидимым.
Установите триггер в главном окне, чтобы сделать его видимым, как только текущий проект был установлен в первый раз.
Вот как обработчик команды 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 связывает свойство видимости _mainWindow
StartupFinished - это DependencyProperty, с которым связано свойство Visibility главного окна, но это можно сделать другими способами.
Сможете ли вы увидеть более быстрое время запуска таким образом?
Да.
Должен ли выбранный проект создаваться в главном потоке, а основной - в другом, или наоборот
Вы должны создать MainWindow в главном потоке, чтобы он разделял тот же Dispatcher с объектом Application. Это означает, что «Выбор проекта» должен быть во втором потоке.
Если вам нужно использовать окно запуска Win32 для скорости
Возможно, это не обязательно. Запуск самого WPF занимает всего доли секунды. Но если это необходимо, описанная выше методика Application.Current.Dispatcher.Invoke
будет работать.
Знаете ли вы, как Blend реализует свое окно запуска?
нет
Нет