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