2017-03-02 263 views
1

是否可以将ListBox ContextMenu的CommandParameter绑定到ListBox的Selected Item?我应该说ContCommand是在主窗口中,当点击上下文菜单项时调用 - 但是,我需要让参数正常工作。WPF:将ListBox ContextMenu的命令参数绑定到ListBox的选定项目

我试过,但绑定失败:

<Window x:Class="ListBoxContextMenu.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:ListBoxContextMenu" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 

    <Grid> 
     <StackPanel> 
      <TextBlock Text="ListBox here:"/> 
      <ListBox ItemsSource="{Binding Items}" MinHeight="100" TabIndex="0" x:Name="LB"> 
       <ListBox.ContextMenu> 
        <ContextMenu> 
         <MenuItem Header="Foo" Command="{Binding ContCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}},Path=SelectedItem}"/> 
        </ContextMenu> 
       </ListBox.ContextMenu> 
      </ListBox> 
     </StackPanel> 
    </Grid> 
</Window> 

C#代码主窗口:

using System.Collections.ObjectModel; 
using System.Windows; 
using System.Windows.Input; 
using MvvmFoundation.Wpf; 

    namespace ListBoxContextMenu 
    { 
     public partial class MainWindow : Window 
     { 
      public MainWindow() 
      { 
       InitializeComponent(); 
       DataContext = this; 
       Loaded += (sender, e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 
       ContCommand = new RelayCommand<object>((object o) => 
       { 
        System.Diagnostics.Debug.WriteLine("Context Menu pressed"); 
       }); 
      } 

      public ObservableCollection<string> Items { get; set; } = new ObservableCollection<string>{"Fred", "Jim", "Sheila"}; 
      public RelayCommand<object> ContCommand { get; set; } 
     } 
    } 
+0

删除代码样本的非相关项目。比如'using' /'NameSpace'和Window属性。只关注阅读它的人的不可或缺的部分。 – OmegaMan

回答

2

ListBox不是ContextMenu的视觉祖先,因为后者驻留在自己的视觉树。

但是你可以绑定到ContextMenuPlacementTarget,这是ListBox

这工作:

<ListBox ItemsSource="{Binding Items}" MinHeight="100" TabIndex="0" x:Name="LB"> 
    <ListBox.ContextMenu> 
     <ContextMenu> 
      <MenuItem Header="Foo" Command="{Binding ContCommand}" 
           CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, 
           Path=PlacementTarget.SelectedItem}"/> 
     </ContextMenu> 
    </ListBox.ContextMenu> 
</ListBox> 
0

上下文菜单在不同的树,所以结合是棘手视情况而定。这里有两个选项:

绑定到通过其名称列表框如

Binding SelectedItem, ElementName=LB 

使用参考名称

有时元素名称绑定失败和一个具有至使用x:ref名称(你有)

Binding Source={x:Reference LB}, Path=SelectedItem 

至于为什么,引用x:Reference

In WPF and XAML 2006, element references are addressed by the framework-level feature of ElementName binding. For most WPF applications and scenarios, ElementName binding should still be used. Exceptions to this general guidance might include cases where there are data context or other scoping considerations that make data binding impractical and where markup compilation is not involved.

+0

''产生绑定错误:System.Windows.Data Error:4:Can not find source for绑定参考'ElementName = LB'。 BindingExpression:路径=的SelectedItem;的DataItem = NULL;目标元素是'MenuItem'(Name ='');目标属性是'CommandParameter'(类型'对象') –

+0

@AdrianS你是否尝试过x:reference绑定呢? – OmegaMan

+0

x:引用绑定导致引发异常:System.Windows.Markup.XamlParseException:'由于循环依赖性,无法调用MarkupExtension.ProvideValue。 MarkupExtension内部的属性不能引用引用MarkupExtension结果的对象。受影响的MarkupExtensions为: 'System.Windows.Data.Binding'行号'18'和行位置'80'。' –

0

添加Mode=FindAncestorRelativeSource结合。

CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=SelectedItem}" 
+0

我得到“System.Windows.Data错误:4:无法找到与参考绑定的源'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.ListBox',AncestorLevel ='1''。BindingExpression:路径=的SelectedItem;的DataItem = NULL;目标元素是'MenuItem'(Name ='');目标属性是'CommandParameter'(类型'对象')“ –