Есть ли способ определить, где привязка 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
здесь
4 ответа
При отладке ошибок привязки 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 является элементом, содержащим свойство с ошибкой, которое является
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.
Может быть, вы могли бы использовать это отличное приложение под названием Snoop. Это бесплатно в CodePlex. Это помогает мне найти несколько проблем связывания и пропустить контексты данных. Это позволяет исследовать все дерево визуалов WPF, а также выдает ошибки привязки.
Надеюсь, что Снуп поможет.
Я новичок в WPF и у меня точно такая же ошибка. Хотя я исправил это сейчас, я действительно не знаю, как... ниже приведены шаги, которые я попробовал:
Прежде всего, у меня есть:
<Menu>
- 2
<ContextMenu>
определяется в<ListBox.ItemTemplate>
Я пытался:
- переместить один
<ContextMenu>
в<ListBox.ItemContainerStyle>
-> ошибка существует - Установить и удалить стиль
HorizontalContentAlignment
а такжеVerticalContentAlignment
за<Menu>
,<ContextMenu>
,<MenuItem>
-> ошибка существует - Установить
Name
атрибут для<MenuItem>
из<ContextMenu>
в<ListBox.ItemTemplate>
-> без ошибок! - Удалить
Name
атрибут -> все еще нет ошибки... - Перезапустите VS -> ошибка, кажется, исчезла навсегда...
В конце концов, у меня есть
<Menu>
<ContextMenu>
определяется в<ListBox.ItemTemplate>
<ContextMenu>
определяется в<ListBox.ItemContainerStyle>
и никто из них не установил стиль HorizontalContentAlignment
а также VerticalContentAlignment
, И ошибка ушла...
Кажется, есть некоторые проблемы с обновлением. Таким образом, для тех, у кого такая же проблема, вы можете попробовать перезапустить VS или установить Name
атрибут для <MenuItem>
...
Ошибка System.Windows.Data: 4 - это не ваша проблема, это проблема, известная WPF. Это связанные комбинированные списки / меню, чьи элементы изменяются динамически. Смотрите это. Кстати, вы можете игнорировать эти ошибки, как правило, приложение работает нормально.