Наличие владельца окна настройки проблемы в родительском конструкторе

Что-то не так в WPF с установкой свойства владельца окна его родительскому объекту в этом родительском конструкторе? Не должно быть, правда? Итак, почему я получаю XamlParseException из следующего кода?

public partial class MainView : Window
{
    private readonly OwnedWindow owned;

    public MainView()
    {
        InitializeComponent();
        owned = new OwnedWindow();

        owned.DataContext = DataContext;

        var window = GetWindow(this);
        owned.Owner = this;  //Setting to window causes the same error

        ...
    }

Я должен пояснить, что удаление owned.Owner = this; также устраняет ошибку времени выполнения.

Сведения об исключении:

Исключение XamlParseException было необработанным

Вызов конструктора по типу "... MainView", который соответствует указанные ограничения привязки вызывают исключение.

Собственно, я посмотрел на Внутреннее Исключение, и он говорит:

Невозможно установить свойство Owner в окно, которое не было показано ранее.

Итак, я изучаю это сейчас.

Ответ 1

Проблема заключается в том, что, поскольку WPF создает только собственное окно при первом показе окна WPF, вы не можете установить окно, пока еще не показанное как Owner (так как это устанавливает владельца собственного окна → owned ", но встроенный дескриптор еще не существует.)

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

Ответ 2

Я подписался на Window.Activated, а не Window.StateChanged. Обязательно отпишитесь на него в обработчике, как указано в комментариях.

    private void OnActivated(object sender, EventArgs eventArgs)
    {
        owned.Owner = this;
        Activated -= OnActivated;
    }

Я принял ответ dlev, потому что это привело меня непосредственно к поиску ответа, даже если он не работал для моей точной ситуации.

Ответ 3

Вам нужен WPF-эквивалент события HandleCreated, который равен SourceInitialized. Это должно работать:

public OwnerWindow()
{
    InitializeComponent();

    SourceInitialized += (s, a) =>
        {
            var owned = new OwnedWindow();
            owned.Owner = this;
        };
}

Обратите внимание, что для этого вам не нужно Show использовать OwnWindow или OwnedWindow.