Приложение WPF закрывается сразу, когда отображается диалоговое окно перед запуском

Использовать CSS vh units!

Вероятно, наиболее очевидным и небедовым способом сделать липкий нижний колонтитул было бы использование новых единиц просмотра css .

Возьмем, к примеру, следующую простую разметку:

header goes here
This page has little content
This is my footer

Если заголовок имеет высоту 80 пикселей, а нижний колонтитул высотой 40 пикселей, мы можем сделать наш липкий нижний колонтитул одним единственное правило в содержимом div:

.content {
    min-height: calc(100vh - 120px);
    /* 80px header + 40px footer = 120px  */
}

Это означает: пусть высота содержимого div должна быть не менее 100% от высоты видового экрана минус комбинированные высоты верхнего и нижнего колонтитула.

Вот и все.

* {
    margin:0;
    padding:0;
}
header {
    background: yellow;
    height: 80px;
}
.content {
    min-height: calc(100vh - 120px);
    /* 80px header + 40px footer = 120px  */
    background: pink;
}
footer {
    height: 40px;
    background: aqua;
}
header goes here
This page has little content
This is my footer

... и вот как работает тот же код с большим количеством содержание в содержимом div:

* {
    margin:0;
    padding:0;
}
header {
    background: yellow;
    height: 80px;
}
.content {
    min-height: calc(100vh - 120px);
    /* 80px header + 40px footer = 120px  */
    background: pink;
}
footer {
    height: 40px;
    background: aqua;
}
header goes here
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.
This is my footer

NB:

1) Высота верхнего и нижнего колонтитула должна быть известна

2) В старых версиях IE (IE8-) и Android (4.4-) не поддерживаются единицы просмотра. ( caniuse )

3) Когда-то у веб-кита возникла проблема с единицами просмотра в правиле calc. Это действительно исправлено ( см. Здесь ), поэтому там нет проблем. Однако, если вы хотите избежать использования calc по какой-либо причине, вы можете обойти это, используя отрицательные поля и отступы с размером окна -

. Так же:

* {
    margin:0;padding:0;
}
header {
    background: yellow;
    height: 80px;
    position:relative;
}
.content {
    min-height: 100vh;
    background: pink;
    margin: -80px 0 -40px;
    padding: 80px 0 40px;
    box-sizing:border-box;
}
footer {
    height: 40px;
    background: aqua;
}
header goes here
Lorem ipsum
This is my footer

21
задан Fyodor Soikin 13 September 2010 в 17:38
поделиться

5 ответов

У меня была похожая проблема. Я провел много времени и не мог решить это. Я был вне времени.

Я не знаю, правильное это решение или нет, но я просто спрятал диалоговое окно входа в систему вместо того, чтобы закрывать его. Он все еще работает

-1
ответ дан Sascha 13 September 2010 в 17:38
поделиться

Если вы установите Application.ShutdownMode на OnExplicitShutdown, можете ли вы избежать включения ShutdownCallback в очередь диспетчера и продолжать делать все, что вы хотите, независимо от окон? Я не проверял это, но кажется потенциальным решением, а также использованием свойства Application.MainWindow , которое можно изменить на лету.

0
ответ дан Jon Comtois 13 September 2010 в 17:38
поделиться

Очень информативный пост, спасибо всем, кто внес вклад. Я использовал плацебо-окно, установив его в главное окно, но не показывало его. Я также установил режим выключения на OnLastWindow. После того, как все диалоговые окна установки были открыты и закрыты, я заменил окно плацебо реальным основным окном и вызвал App.Run (). Это, вероятно, не лучшая практика, но она работает и работает быстро.

Application app = new App();

MainWindow y = new MainWindow();
app.MainWindow = y;
y.WindowStartupLocation = WindowStartupLocation.CenterScreen;
app.ShutdownMode = ShutdownMode.OnLastWindowClose;
//do lots of setup work to include authentication
MainWindow x = new MainWindow(containerdata)
app.MainWindow = x;
App.Run()
1
ответ дан cnotpc 13 September 2010 в 17:38
поделиться

Это кажется глючным.

Я обычно ничего не помещаю в Main(), я позволяю no-arg app.Run() вызываться и вызывать все, что мне нужно, в методе OnStartup, но это не изменит поведение, которое вы видите .

Всякий раз, когда мне нужно что-то показать до того, как мое главное окно приложения будет готово к отображению, например, собирать информацию или показывать заставку, я делаю это во втором потоке.

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    // show splash
    var thread = new Thread(() =>
    {
        Dispatcher.CurrentDispatcher.BeginInvoke
            ((Action)(() => new MySplashWindow().Show()));
        Dispatcher.Run();
    }
    thread.SetApartmentState(ApartmentState.STA);
    thread.IsBackground = true;
    thread.Start();

    // run configuration steps

    // instantiate and show main window
}

Очевидно, что если вы звоните ShowDialog() во втором потоке, вам необходимо убедиться, что вы получите ответ, прежде чем показывать главное окно. У него есть преимущество в том, что вы можете запускать другие задачи начальной загрузки, ожидая пользовательского ввода в определенной части; это действительно зависит от того, насколько последовательны ваши различные задачи.

Может быть, это помогает в вашем случае; возможно нет - просто мысль.

2
ответ дан Jay 13 September 2010 в 17:38
поделиться

По умолчанию ShutdownMode приложения WPF имеет вид OnLastWindowClose. В своем коде вы показываете одно окно, а затем закрываете его. Таким образом, последнее окно закрывается, и приложение закрывается. Затем при закрытии вы показываете другое окно. Поскольку приложение закрывается, окно немедленно закрывается.

Так что все работает так, как вы спроектировали и запрограммировали.

Однако вы хотите сделать что-то другое: окно, которое вы сначала показываете как единственное окно, должно быть «специальным окном», и после его закрытия вы хотите продолжить выполнение, показать свое «главное окно» и затем выйти После закрытия приложения (или всех окон, связанных с приложением).

Самый простой способ: сначала установить режим выключения OnExplicitShutdown, затем, после показа главного окна, установить его в OnLastWindowClose или OnMainWindowClose. В коде:

public static void Main()
{
    var app = new App();
    app.InitializeComponent();

    app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
    new DialogWindow().ShowDialog();

    var mainWindow = new MainWindow();
    app.MainWindow = mainWindow;
    app.Run(mainWindow);
    // When the window has loaded, it should then set the app.ShutdownMode to what you actually want.
}

РЕДАКТИРОВАТЬ: Я не уверен, что именно вы делаете. Код, который вы дали, не скомпилируется, поскольку при правильном использовании класса приложения WPF (с действием сборки App.xaml в качестве ApplicationDefinition) метод Main уже определен. Если у вас просто есть класс, производный от Application, у вас нет метода InitializeComponent (). Единственный способ получить код для компиляции - вручную изменить действие сборки на Page. Однако в этом случае Application.Current == app.

Итак, происходит следующее:

  1. Приложение запускается. Поскольку до сих пор не было создано ни одного WPF-приложения, Application.Current имеет значение null. Это также означает, что диспетчерский цикл не выполняется, а диспетчерские сообщения не обрабатываются (обратите внимание, что диспетчерский цикл также обрабатывает сообщения Windows).
  2. Новый App-объект создан. Поскольку Application.Current имеет значение null, он устанавливает себя как Application.Current.
    • Application.Current.MainWindow имеет значение null, а Application.Current.Windows - пустой список.
    • Поскольку ShutdownMode имеет значение OnLastWindowClose, после закрытия последнего окна текущего приложения (т.е. приложения) начинается отключение.
  3. DialogBox отображается модально. Поскольку не работает ни один диспетчерский цикл, ShowDialog () сам выполняет «локальный» диспетчерский цикл.
    • На самом деле это две части: сначала создается окно. Он принадлежит текущему приложению, поэтому он добавляет себя в Application.Current.Windows. Так как это первое показанное окно и Application.Current.MainWindow имеет значение null, оно также устанавливает себя как главное окно. Во-вторых, окно показывается модально.
    • Поскольку приложение.Current.Windows теперь не пусто, после его запуска начнется отключение.
  4. Пользователь закрывает диалоговое окно. Как часть закрытия, окно удаляет себя из Application.Current.Windows. Кроме того, поскольку это MainWindow, для него установлено значение null. Поскольку Application.Current.Windows теперь пусто, начинается отключение. Однако, поскольку не работает ни один диспетчерский цикл, пока ничего не сделано (установлен только внутренний флаг или аналог).
    • Если бы вы использовали app.Run(new DialogWindow()); app.Run(new MainWindow());, у вас было бы исключение при создании MainWindow, так как в этом случае цикл диспетчера работает правильно. Таким образом, он может фактически отключиться, поэтому, когда MainWindow создается, он генерирует исключение, поскольку цикл диспетчера уже отключен.
  5. Основное окно создано. Как и выше, он добавляет себя в Application.Current.Windows и устанавливает себя как Application.Current.MainWindow.
    • Однако условие для закрытия приложения уже достигнуто. Но пока приложение не имело возможности что-либо делать.
  6. Теперь вызывается Run (). Диспетчерская петля запускается снова и теперь имеет возможность завершить работу приложения. Поэтому он закрывает приложение и закрывает все открытые окна.

Опять же, без ошибок.

Так что один из способов решить эту проблему - перейти на OnExplicitShutdown. Затем на шаге 4 причина прекращения работы не достигается. Лучше (как в обычном приложении WPF) было бы иметь правильное ApplicationDefinition. Удалите StartupUri из App.xaml и вместо этого обработайте событие Startup:

private void OnStartup(object sender, StartupEventArgs e)
{
    this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
    new DialogWindow().ShowDialog();

    var mainWindow = new MainWindow();
    this.ShutdownMode = ShutdownMode.OnLastWindowClose; // or OnMainWindowClose
    mainWindow.Show();
}

Так как при закрытии диалогового окна у нас есть OnExplicitShudown, у приложения нет причин начинать закрываться в этой точке. Затем, после создания MainWindow, у нас снова есть окно как главного окна и как одно из окон приложения. Тогда мы можем перейти в режим выключения, который нам действительно нужен, и показать главное окно.

32
ответ дан Daniel Rose 13 September 2010 в 17:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: