WPF: при программном открытии контекстного меню теряется контекст данных

#wpf #xaml #datacontext

Вопрос:

Я хотел бы повторно использовать контекстное меню a ListViewItem , добавив кнопку переключения внутри самого элемента, которая открывает его. Само контекстное меню работает правильно, однако, когда я открываю его с помощью кнопки переключения (просто установив ее свойство IsOpen на True ), команды внутри больше не работают. Похоже, в контекстном меню больше нет DataContext этого.

 lt;ListViewgt;  lt;ListView.ItemContainerStylegt;  lt;Style TargetType="{x:Type ListViewItem}"gt;  lt;Setter Property="ContextMenu"gt;  lt;Setter.Valuegt;  lt;ContextMenugt;  lt;MenuItem  Header="Restore"  Command="{Binding RestoreCommand}" /gt;  lt;MenuItem  Header="Delete"  Command="{Binding DeleteCommand}"/gt;  lt;/ContextMenugt;  lt;/Setter.Valuegt;  lt;/Settergt;  lt;/Stylegt;  lt;/ListView.ItemContainerStylegt;   lt;ListView.Viewgt;  lt;GridViewgt;  lt;!-- My columns here --gt;  lt;GridViewColumngt;  lt;GridViewColumn.CellTemplategt;  lt;DataTemplategt;  lt;ToggleButton IsChecked="{Binding Path=ContextMenu.IsOpen, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"/gt;  lt;/DataTemplategt;  lt;/GridViewColumn.CellTemplategt;  lt;/GridViewColumngt;  lt;/GridViewgt;  lt;/ListView.Viewgt;  

Есть какие-нибудь предложения? Спасибо

Ответ №1:

Проблема в том, что контекстное меню, открытое косвенно таким образом, не имеет DataContext . Чтобы «назначить» его, вы должны использовать свойство PlacementTarget , чтобы указать, к какому элементу управления оно привязано.

Для выполнения этой задачи вы можете либо создать пользовательское поведение, либо, если вы предпочитаете чисто xaml-решение:

 lt;!-- xmlns:b="http://schemas.microsoft.com/xaml/behaviors" --gt;   lt;GridViewColumngt; lt;GridViewColumn.CellTemplategt;  lt;DataTemplategt;  lt;ToggleButton  x:Name="MoreActionsButton"  IsChecked="{Binding ContextMenu.IsOpen, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}, Mode=OneWayToSource}"gt;  lt;b:Interaction.Triggersgt;  lt;b:EventTrigger EventName="Checked"gt;  lt;b:ChangePropertyAction  TargetObject="{Binding ContextMenu, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"  PropertyName="PlacementTarget"  Value="{Binding ElementName=MoreActionsButton}" /gt;  lt;/b:EventTriggergt;  lt;/b:Interaction.Triggersgt;  lt;/ToggleButtongt;  lt;/DataTemplategt; lt;/GridViewColumn.CellTemplategt; lt;/GridViewColumngt;