Как получить доступ к элементу управления из меню ContextMenu через визуальное дерево?

Это, кажется, довольно популярная тема, но ...

У меня есть следующий XAML:

<internal:MyCommandObject x:Name="CommandModel"/>

<Button DockPanel.Dock="Bottom" Command="{Binding DoAction, ElementName=CommandModel}">
    <Button.ContextMenu>
        <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
            <MenuItem Command="{Binding DoAction, ElementName=CommandModel}"/>
        </ContextMenu>
    </Button.ContextMenu>
    Click Me
</Button>

Сейчас,MyCommandObject это элемент управления, который предоставляет динамические команды от егоDataContext, Вы знаете, что будет дальше. :)

В принципе, команда кнопки работает отлично - когда я нажимаю на нее,DoAction команда наMyCommandObject исполняется отлично. Однако команда в элементе меню не выполняется. Я пробовал разные приемы, такие как настройка контекстного меню.datacontext бытьplacementTarget поэтому он может проходить по визуальному дереву элементов управления и т. д., но ничего не делает.

Какой конкретный раскладRelativeSource а такжеCommandTarget руны мне нужно, чтобы это заработало?

Ответы на вопрос(1)

Решение Вопроса

Это происходит потому, чтоDataContext="{Binding PlacementTarget,... привязка установит кнопку как MenuItemsDataContext но это не добавитContextMenu к VisualTree вашего окна и вот почемуElementName связывание не будет работать. Простой обходной путь для использованияElementName bindings должен добавить это в ваш код позади Window / UserControl:

NameScope.SetNameScope(contextMenuName, NameScope.GetNameScope(this)); 

Другое решение состоит в том, чтобы сделать это -

<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">   
    <MenuItem Command="{Binding DataContext.DoAction}"/>   
</ContextMenu>

DataContext="{Binding PlacementTarget,... установит Button (Placementtarget) в качестве DataContext вашего ContextMenu, поэтому вы можете использовать DataContext Button для связывания команды.

Update:

Вы можете попробовать и использоватьNameScope.NameScope Attached Property установить NameScope в XAML, но я не уверен, как вы получите NameScope родительского окна без кода!

Вам придется сделать что-то похожее на следующую статью Джоша Смита, он предоставляет способ сделать это в XAML; но это также включает в себя код (больше, чем эта строка кода) -

Включить привязки ElementName с ElementSpy

Есть какая-то конкретная причина не использовать эту единственную строку кода?

 Webreaper27 авг. 2015 г., 22:30
Weird. Я не думаю, что это был я!
 06 июл. 2012 г., 08:22
@Webreaper Не уверен, говорите ли вы только о своем сценарии или в общих чертах, но в основном файлы XAML компилируются в BAML во время сборки (глядя на ваш xaml, который выглядит так же); Я бы предложил вам сослаться на эти ссылки -Compiled XAML = BAML not IL а такжеB is for... BAML
 06 июл. 2012 г., 14:16
Имеет смысл; Я не использовал свободный XAML, но согласноthis сообщениеA loose XAML file can't include the x:Class XAML keyword; так что если это правильно, то вы не сможете достичь того, чего хотите!
 27 авг. 2015 г., 17:55
Не уверен, почему -1 через 3 года странно .....
 Webreaper05 июл. 2012 г., 12:22
Спасибо за это. Я пытаюсь не использовать выделенный код, если это возможно - возможно ли определить NameScope в XAML? К сожалению, я не могу установить контекст данных пункта меню как кнопку, которая предоставляет команду. Это контекстное меню для сетки, и мне нужен DataContext выбранного элемента, чтобы я мог передать свойства из этого в качестве параметров в команду.

Ваш ответ на вопрос