将ListBox中的SelectedItem绑定到ContextMenu中的CommandParameter

时间:2012-08-28 23:16:23

标签: wpf binding contextmenu datatemplate observablecollection

虽然这个问题与其他人发布的非常相似,但它有一些变化!我在 ListBox 中有 ObservableCollection 项,并使用 DataTemplate 来显示某些集合成员。但是,我定义了 ContextMenu ,因此我可以使用命令参数执行在我的ViewModel中定义的 DelegateCommands

除了我需要使用ListBox中选择的项的CommandParameter为ViewModel中的Command提供一个参数,所以我的所有绑定都在这里工作,以便命令知道要对哪个项进行操作。但这是不可能的,因为我更改了ContextMenu DataContext,因此我可以访问ViewModel中的DelegateCommands。

我收到以下错误: System.Windows.Data错误:4:找不到与引用'ElementName = instrumentListView'绑定的源。 BindingExpression:路径=的SelectedItem;

ViewModel中的Command按我的意愿调用,但其参数始终为null。

我还尝试绑定到集合中的项目,但它们不可见,因为我必须切换我的DataContext。

以下是缩写的XAML文件:

            <ListBox x:Name="instrumentListView" ItemsSource="{Binding Instruments}" >              
                <ListBox.ItemTemplate>
                    <DataTemplate>
                       <StackPanel x:Name="instrumentStackPanel" HorizontalAlignment="Left" Orientation="Horizontal" Height="30" UseLayoutRounding="True" Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}">                            
                        <Image Source="{Binding InstrumentIcon}" Margin="0,0,10,0"></Image>
                        <Label Content="{Binding Instrument}"></Label>
                        <StackPanel.ContextMenu >
                            <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                                <MenuItem Header="Add Instrument" Command="{Binding Path=AddInstrumentToTest}" CommandParameter="{Binding Instrument}"/>
                                <MenuItem Header="Remove Instrument" Command="{Binding Path=RemoveInstrumentFromTest}" CommandParameter="{Binding Instrument}"/>
                            </ContextMenu>
                        </StackPanel.ContextMenu>
                        </StackPanel>                            
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

以下是我的ViewModel的副本:

     public class ViewModel : INotifyPropertyChanged
    {
        public DelegateCommand<string> AddInstrumentToTest { get; set; }
        public DelegateCommand<string> RemoveInstrumentFromTest { get; set; }
        private ObservableCollection<IInstrument> instruments = new ObservableCollection<IInstrument>();

        public ViewModel()
        {
            this.AddInstrumentToTest = new DelegateCommand<string >(this.OnaddInstrumentToTest, this.canAddInstrument);
            this.RemoveInstrumentFromTest = new DelegateCommand<string >(this.OnremoveInstrumentFromTest, this.canRemoveInstrument);      
        }

        public ObservableCollection<IInstrument> Instruments
        {
            ...
        }

        public void OnaddInstrumentToTest(string inst) {...}
        public void OnremoveInstrumentFromTest(string inst) {...}
        public bool canRemoveInstrument(string inst) {...}
        public bool canAddInstrument(string inst) {...}

        ...
}

这是IInstrument界面:

        public interface IInstrument
        {        
            string Model {get;set;}       
            string SerialNumber {get;set;}    
            InstrumentCommInterface.InstrumentInterface InstrumentComm {get;set;} 
            InstrumentClassification.InstrumentClass InstrumentClass {get;set;} 
            string FirmwareVersion {get;set;}  
            string Address {get;set;}
            string Port {get;set;}
            Lazy<IInstrumentFactory, IInstrumentPlugInMetaData> PlugInType {get;set;}
            string Instrument {get;set;}
            BitmapImage InstrumentIcon {get;set;}
            bool SelectedForTest {get;set;}
            ObservableCollection<string> Channels {get;set;}        
        }

1 个答案:

答案 0 :(得分:0)

我会保留DataContext并通过上下文菜单标记进行隧道传输。

<!-- Keep complete ListBox, allows acces of selected item and higher up DataContext -->
<StackPanel Tag="{Binding RelativeSource={RelativeSource AncestorType=ListBox}}">
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"
             Tag="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">

所以现在DataContext仍然是您的项目,如果您需要使用所选项目:

Tag.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}