Подтвердить что ты не робот

Есть ли способ определить, где объявляется/создается привязка WPF?

У меня есть проект, который бросает некоторые ошибки привязки данных. Например:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

Мой вопрос заключается в том, есть ли способ определить, где это обязательство фактически объявлено (либо оно объявлено в XAML, либо в коде).

Что я пробовал до сих пор:

  • добавлена ​​трассировка отладки для пространства имен System.Windows.Data с набором уровней o All; это не принесло никакой полезной информации.
  • попытался выполнить текстовый поиск в проекте для слова Binding в надежде найти все выражения привязки, у которых Path установлен на HorizontalContentAlignment; Я нашел только один и удалил его, но я все еще получаю сообщение, которое, похоже, указывает, что это не ошибка.

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

ОБНОВЛЕНИЕ

После немного большего поиска я уверен, что это как-то вызвано стилем, применяемым к MenuItem. Тем не менее, я все еще не могу указать местоположение, в котором объявляется ошибочная привязка.

ОБНОВЛЕНИЕ 2

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

Как оказалось, привязка объявляется в стиле. И стиль не в моем приложении. Это, вероятно, стиль по умолчанию для MenuItem. Поэтому, чтобы исправить проблему, я только вручную установил HorizontalContentAlignment на всех MenuItems. Причина ошибки связана с порядком операций, так как этот MenuItem генерируется в коде. Я отдельно опубликую новый вопрос.

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

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

Я разместил еще один вопрос о том, как стиль/привязка применяется к MenuItems здесь.

4b9b3361

Ответ 1

При отладке ошибок привязки WPF я считаю, что проще всего разбить ошибку на точки с запятой и начать с конца

  • System.Windows.Data Error: 4 :
  • Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment;
  • DataItem=null;
  • target element is 'MenuItem' (Name='');
  • target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

Итак, начиная с конца:

  • # 5 сообщает вам, какое свойство содержит привязку, которая терпит неудачу. В вашем случае это HorizontalContentAlignment

  • # 4 - это элемент, содержащий свойство failing, которое является MenuItem без свойства Name, чтобы идентифицировать его с помощью

    Итак, у вас есть <MenuItem HorizontalContentAlignment="{Binding ...}" />, который вызывает ошибку привязки.

  • # 3 - это DataItem или DataContext, который находится за целевым элементом. Кажется, для вас это null, но это не проблема, так как похоже, что ваша привязка не ссылается на DataContext.

    Но это означает, что MenuItem не является частью вашего обычного VisualTree, так как обычно DataContext наследуется от родительского объекта.

  • # 2 содержит фактическую ошибку привязки и информацию о привязке. На самом деле его можно разбить на несколько частей.

    • Cannot find source for binding

    • with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''.

    • BindingExpression:Path=HorizontalContentAlignment;

    "Невозможно найти источник" означает, что привязка не может найти объект-источник для привязки, и в вашем случае этот исходный объект должен быть {RelativeSource AncestorType={x:Type ItemsControl} (FindAncestor и AncestorLevel=1 по умолчанию для RelativeSource, поэтому я игнорирую их)

    И последняя часть # 2 показывает Path, с которой вы пытаетесь привязать: HorizontalContentAlignment

Итак, чтобы все это было вместе, где-то в вашем коде есть <MenuItem>, который пытается привязать его HorizontalContentAlignment к ItemsControl.HorizontalContentAlignment, но привязка не может найти ItemsControl.

Вы используете привязку RelativeSource FindAncestor, чтобы найти ItemsControl, который ищет визуальное дерево, чтобы найти ближайший ItemsControl, и он не находит его, поэтому не должно быть ItemsControl выше в Иерархия VisualTree из MenuItem.

Я часто вижу эту проблему с ContextMenus, потому что они не являются частью одного и того же VisualTree как остальной части вашего XAML-кода. (Чтобы ссылаться на объект в главном VisualTree, к которому привязан ContextMenu, вы можете использовать свойство PlacementTarget, например этот пример.

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

В зависимости от размера моего приложения, я обычно делаю одно из следующих действий:

  • Найдите приложение для "целевого элемента" из ошибки привязки (в вашем случае, MenuItem) и посмотрите, устанавливает ли какой-либо из них "целевое свойство" (HorizontalContentAlignment) с привязкой

  • Найдите приложение для "целевого свойства" из ошибки привязки (HorizontalContentAlignment), чтобы найти связывание, вызывающее эту проблему.

  • Найдите приложение для чего-то достаточно уникального из текста привязки, показанного в ошибке привязки. В вашем случае вы можете попробовать выполнить поиск по {x:Type ItemsControl}, который будет частью вашей привязки RelativeSource, и не должно быть слишком много результатов поиска для такой фразы.

  • Используйте сторонний инструмент, например Snoop или WPF Inspector для отслеживания ошибки привязки во время выполнения.

    Я только использовал Snoop раньше, но для его использования вам нужно запустить приложение и запустить Snoop против него, чтобы проверить ваше приложение VisualTree во время его работы. Затем вы можете выполнить поиск в VisualTree, введя что-то вроде "MenuItem" в строке поиска, чтобы отфильтровать визуальное дерево для всех MenuItems, затем просмотрите их свойства, чтобы узнать, какая из них имеет ошибку привязки (свойство HorizontalContentAlignment будет выделено красным цветом из-за ошибки привязки).

    Следует отметить, что если ваш MenuItem находится внутри ContextMenu, вам нужно открыть это ContextMenu для отображения элементов MenuItems и отображения в Snoop.

Ответ 2

Возможно, вы могли бы использовать это превосходное приложение под названием Snoop. Это бесплатно в CodePlex. Это помогает мне найти несколько проблем с привязкой и контексты данных missin. Он позволяет исследовать все визуальное дерево WPF, а также дать вам ошибки привязки.

Надежда Snoop может помочь.

Ответ 3

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

Прежде всего, у меня есть:

  • a <Menu>
  • 2 <ContextMenu>, определенный в <ListBox.ItemTemplate>

Я попытался:

  • переместить один <ContextMenu> в <ListBox.ItemContainerStyle> → ошибку существует
  • Установите и удалите стиль HorizontalContentAlignment и VerticalContentAlignment для <Menu>, <ContextMenu>, <MenuItem> → ошибки
  • Установите атрибут Name для <MenuItem> <ContextMenu> в <ListBox.ItemTemplate> без ошибок!
  • Удалить атрибут Name по-прежнему нет ошибки...
  • Перезагрузите VS → ошибка, которая исчезла навсегда...

В конце концов, у меня есть

  • a <Menu>
  • a <ContextMenu>, определенный в <ListBox.ItemTemplate>
  • a <ContextMenu>, определенный в <ListBox.ItemContainerStyle>

а NONE из них установили стиль HorizontalContentAlignment и VerticalContentAlignment. И ошибка ушла...

Кажется, есть проблема с обновлением. Итак, для тех, у кого такая же проблема, вы можете попробовать перезапустить VS или установить атрибут Name для <MenuItem>...

Ответ 4

Ошибка System.Windows.Data: 4 - это не ваша проблема, это проблема с WPF. Это относится к спискам со списком/меню, элементы которых изменяются динамически. См. это. Кстати, вы можете игнорировать эти ошибки, обычно приложение работает нормально.