WPF Что происходит, когда ширина дочернего элемента привязана к фактической ширине родительского элемента

Итак, если у меня есть привязка по ширине дочернего объекта, которая связывает его с его родительским объектом ActualWidth, что произойдет?

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

Однако это предполагает, что привязка не распространяется так быстро. Я все еще не понимаю, когда связанное значение распространяется на цель. Все зависит от того, когда изменится фактическое значение ширины родительского объекта. Это происходит после завершения макета? а потом связанные штуки обновлять? Каждая привязка прерывает текущий выполняющийся код для обновления целевого значения? если нет, не возникнет ли проблем, если одна привязка распространяет изменение, требующее перерисовки, тогда другая привязка распространяет другое изменение, которое вызывает перерисовку и т. д.

Некоторые люди спрашивали, в чем была моя настоящая проблема:

Поэтому изначально я хотел иметь контрольную растяжку, чтобы заполнить доступное пространство. Достаточно просто, но я хотел, чтобы это было в программе просмотра прокрутки. Scrollviewer предоставляет своим дочерним элементам бесконечное пространство во время измерения. Поэтому вместо этого вы можете привязать ширину и высоту дочернего элемента управления к фактической ширине и фактической высоте родительского элемента; макет делает второй проход, и все кажется шикарным.

Однако позже у меня возникли проблемы аналогичного типа с растяжкой элемента управления в шаблоне управления, но затем я обнаружил, что я могу установить minwidth и alignment = stretch, чтобы он растягивался.

Тем не менее, я отчетливо помнил, как пытался это сделать ранее на другом моем элементе управления, и он не работал, поэтому я вернулся и попытался выяснить, в чем разница между двумя случаями. По сути, все сводилось к тому, что один из них находился в стековой панели несколькими уровнями выше.

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

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


person James Joshua Street    schedule 11.07.2013    source источник
comment
Только не беспокойтесь. У вас, вероятно, будет Control, у которого есть параметры предыдущего размера. Просто поместите элемент управления на Stackpanel и не устанавливайте его ширину. У него будет Stacpanel.ActualWidth.   -  person Henk Holterman    schedule 12.07.2013
comment
Определенно могут быть проблемы с «рекурсивными» привязками, которые приводят к проблемам с обновлением. Например, попробуйте вложить сетки друг в друга с помощью общих ссылок на области общего размера. Вы можете попасть в некоторые состояния, когда сетки борются из-за своих измерений, и вы можете столкнуться с мерцанием между разными размерами при непрерывном обновлении проходов макета. Лучше избегать создания таких условий.   -  person Dan Bryant    schedule 12.07.2013
comment
Я очень много пробовал. Проблема в том, что я не могу разместить точку останова внутри метода переопределения сетки, поэтому я не могу видеть каждый шаг и быть уверенным, что все происходит так, как я думаю. Я все время думаю, что этому сайту нужен раздел для общего обсуждения того, как все работает, а не для конкретных вопросов. Можно ли куда-нибудь пойти и просто открыть диалог чата с группой людей, знающих wpf?   -  person James Joshua Street    schedule 12.07.2013
comment
На самом деле вы можете установить точку останова внутри MeasureOverride, но может оказаться более целесообразным использовать Debug.Writeline. :-) Также это звучит очень похоже на проблему поиска применения. Какова реальная проблема, на которую вы пытаетесь ответить?   -  person AlSki    schedule 12.07.2013
comment
я отвечу в основном посте   -  person James Joshua Street    schedule 12.07.2013


Ответы (1)


Согласно перечислению DispatherPriority, DataBinding встречается перед Rendering.

  • Отправлять
  • Нормальный - здесь запускаются конструкторы.
  • DataBind
  • Обработка
  • Загружено
  • Задний план
  • ContextIdle
  • ApplicationIdle
  • SystemIdle
  • Неактивный
  • Недействителен
  • Вход

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

Однако рендеринг может привести к обновлению вашей привязки, поэтому, если процесс рендеринга родительской панели увеличит ширину панели (например, родительская панель, помещенная внутри другой панели, которая автоматически растягивает свои дочерние элементы, чтобы занять 100% пространства как Grid или последний элемент в DockPanel), тогда он вызовет обновление привязки и увеличит ширину дочернего элемента во время цикла рендеринга.

Вторая часть этого SO-ответа также может помочь вам понять. Также обратите внимание на №6.

Последовательность событий при создании и отображении окна

В соответствии с запросом, вот последовательность основных событий в WPF при создании и отображении окна:

  1. Конструкторы и геттеры / сеттеры вызываются по мере создания объектов, включая PropertyChangedCallback, ValidationCallback и т. Д. Для обновляемых объектов и любых объектов, которые наследуются от них.

  2. Когда каждый элемент добавляется к визуальному или логическому дереву, его событие Intialized запускается, что приводит к тому, что стили и триггеры применяются в дополнение к любой специфичной для элемента инициализации, которую вы можете определить [примечание: инициализированное событие не запускается для листьев в логическом дереве если в его корне нет PresentationSource (например, Window)]

  3. Окно и все несвернутые визуальные элементы на нем измеряются, что вызывает ApplyTemplate для каждого элемента управления, что вызывает дополнительное построение дерева объектов, включая дополнительные конструкторы и геттеры / сеттеры.

  4. Окно и все несвернутые визуальные элементы в нем упорядочены.

  5. Окно и его потомки (как логические, так и визуальные) получают событие Loaded.

  6. Любые привязки данных, которые не удалось установить при первой установке, повторяются.

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

Шаги 1-2 выполняются при создании окна, независимо от того, отображается оно или нет. Остальные шаги обычно не выполняются, пока не отобразится окно, но они могут произойти раньше, если запускаться вручную.

person Rachel    schedule 12.07.2013