SizeToContent для Window: медленная загрузка приводит к тому, что окно отображается маленьким, ТОГДА изменяет размер правильно

Итак, у меня есть окно, которое появляется (во время нормальной работы программы) по запросу пользователя для отображения некоторой контекстно-зависимой информации. В этом окне много элементов, поэтому загрузка занимает 0,5 - 1 сек. Однако, поскольку я ожидаю, что это окно будет содержать несколько различных типов информации в зависимости от контекста, ширина и высота его содержимого могут различаться. Таким образом, я установил значение SizeToContent на "WidthAndHeight", чтобы разрешить изменение размера окна в зависимости от того, какой контент связан с ним.

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

Есть ли способ заставить окно отображать только ПОСЛЕ того, как оно полностью отрендерилось?

Вещи, которые я пробовал:

  • установите видимость окна на "Скрытый", а затем установите его на "Видимый" в обработчике событий ContentRendered: окно никогда не отображалось.

  • установите непрозрачность окна равной 0, а затем установите его равным 1 в обработчике событий ContentRendered: непрозрачность содержимого в самом окне задается равной 0, а затем равной 1.

Обновление: еще одна попытка

Я также попытался установить Window.WindowState на "Minimized" в XAML, а затем установить его на "Normal" в обработчике событий ContentRendered. Кажется, это работает частично, хотя ширина самого окна больше, чем должна быть. Хуже того, кажется, что содержимое в окне отображается в соответствии с правильным размером для окна, а затем окно становится больше без повторной обработки содержимого. Таким образом, содержимое не центрируется в окне, и у нас есть неприятный черный прямоугольник справа от содержимого, который представляет разницу между правильным размером окна и текущим (большим) размером. Когда я изменяю размер окна вручную, захватывая край окна, содержимое перерисовывается правильно, и все выглядит хорошо. Но как заставить такой повторный рендеринг в коде? Window.UpdateLayout() не работает.

3 ответа

Решение

Хорошо, я нашел свою ошибку. SizeToContent, установленный в WidthAndHeight, работает нормально, пока DataContext для нового окна был установлен ДО того, как вы откроете окно. Как в:

secondaryWindow.DataContext = viewModel;  

secondaryWindow.Show();

скорее, чем:

secondaryWindow.Show();

secondaryWindow.DataContext = viewModel;  

как у меня было.

Таким образом, происходило то, что размер окна подходил по размеру в случае, когда DataContext был нулевым, а затем изменял размер, когда был установлен DataContext.

Спасибо Elad Katz за добавление решения, которое косвенно заставило меня найти эту ошибку.

Хорошо, я нашел решение, которое работает. Не идеально, но это работает.

Сначала я установил Window.WindowState на "Свернутый" в XAML. Это предотвращает появление окна на экране во время рендеринга. Затем я подписался на событие ContentRendered для окна и добавил следующий код в обработчик:

this.WindowState = System.Windows.WindowState.Normal;
this.MaxWidth = MainContentPresenter.ActualWidth;
this.Height = MainContentPresenter.ActualHeight;

this.InvalidateVisual();

где MainContentPresenter - это ContentPresenter для окна. ViewModel привязан к этому элементу, поэтому содержимое отображается там.

Обратите внимание, что вы можете знать, какой размер окна нужно событие, не показывая его вообще.

если у вас есть элемент управления, который вы хотите знать размер, который он хочет, вы можете сделать следующее

// I'm picking Button here, but any control could be put here, be it
// Window or whatever:

Button b = new Button();

// I'm putting some content to see that it actually measures it children. If you'll put more text here
// you'll see bigger size
b.Content = "Hello";

// I'm manually measuring the control, passing in double.PositiveInfinity so that the control
// would give me the size it wants, regardless of any constraints (you can put constraints here
// if you like)
b.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

// After Measure is called, the Property DesiredSize become relevant, and contains the size that the
// Control needs to show all of its contents.
MessageBox.Show(b.DesiredSize.ToString());
Другие вопросы по тегам