在将ContextMenu一个ListBox到CommandParameter绑定的SelectedItem [英] Bind SelectedItem in a ListBox to CommandParameter in a ContextMenu

查看:212
本文介绍了在将ContextMenu一个ListBox到CommandParameter绑定的SelectedItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然这个问题是非常相似的他人发布,它有几个捻!我有一个的ListBox 的ObservableCollection 项目,并使用的DataTemplate 显示一些集合成员的。不过,我有一个文本菜单确定这样我就可以执行 DelegateCommands 使用的命令参数在我的视图模型定义的。

我的所有绑定都在这里工作到,但我需要这样的命令知道要操作这些项目提供使用ListBox中的所选项目的CommandParameter的命令在视图模型的参数。但是,这是不可能的,因为我改变了文本菜单DataContext的,所以我可以在我的ViewModel的DelegateCommands得到的。

我收到以下错误:
System.Windows.Data错误:4:无法为参照的ElementName = instrumentListView'绑定找到源头。 BindingEx pression:路径=的SelectedItem;

在视图模型的命令被称为我的愿望,但它的参数始终为空。

我也试图绑定到集合中的项目,但他们是不可见的,因为我不得不改用我的DataContext。

以下简称XAML文件:

 < ListBox的X:名称=instrumentListView的ItemsSource ={约束力的文书}>
                < ListBox.ItemTemplate>
                    <&DataTemplate的GT;
                       < StackPanel的X:名称=instrumentStackPanel的Horizo​​ntalAlignment =左的方向=横向HEIGHT =30UseLayoutRounding =真标签={绑定的DataContext,的RelativeSource = {的RelativeSource AncestorType =列表框}}>
                        <图像来源={结合InstrumentIcon}保证金=0,0,10,0>< /图像>
                        <标签内容={约束力的文书}>< /标签>
                        < StackPanel.ContextMenu>
                            <文本菜单的DataContext ={结合PlacementTarget.Tag,的RelativeSource = {自我的RelativeSource}}>
                                <菜单项标题=添加仪器命令={绑定路径= AddInstrumentToTest}CommandParameter ={约束力的文书}/>
                                <菜单项标题=删除仪命令={绑定路径= RemoveInstrumentFromTest}CommandParameter ={约束力的文书}/>
                            < /文本菜单>
                        < /StackPanel.ContextMenu>
                        < / StackPanel的>
                    < / DataTemplate中>
                < /ListBox.ItemTemplate>
            < /列表框>

下面是我的视图模型的副本:

 公共类视图模型:INotifyPropertyChanged的
    {
        公共DelegateCommand<串GT; AddInstrumentToTest {搞定;组; }
        公共DelegateCommand<串GT; RemoveInstrumentFromTest {搞定;组; }
        私人的ObservableCollection< IInstrument>仪器=新的ObservableCollection< IInstrument>();        公共视图模型()
        {
            this.AddInstrumentToTest =新DelegateCommand<串GT;(this.OnaddInstrumentToTest,this.canAddInstrument);
            this.RemoveInstrumentFromTest =新DelegateCommand<串GT;(this.OnremoveInstrumentFromTest,this.canRemoveInstrument);
        }        公众的ObservableCollection< IInstrument>仪器
        {
            ...
        }        公共无效OnaddInstrumentToTest(字符串研究所){...}
        公共无效OnremoveInstrumentFromTest(字符串研究所){...}
        公共BOOL canRemoveInstrument(字符串研究所){...}
        公共BOOL canAddInstrument(字符串研究所){...}        ...
}

这里是IInstrument接口:

 公共接口IInstrument
        {
            字符串模式{获取;设置;}
            字符串的SerialNumber {获取;设置;}
            InstrumentCommInterface.InstrumentInterface InstrumentComm {获取;集;}
            InstrumentClassification.InstrumentClass InstrumentClass {获取;集;}
            字符串FirmwareVersion {获取;设置;}
            字符串地址{获取;设置;}
            字符串端口{获取;设置;}
            懒惰< IInstrumentFactory,IInstrumentPlugInMetaData> PlugInType {获取;设置;}
            弦乐器{获取;设置;}
            BitmapImage的InstrumentIcon {获取;集;}
            布尔SelectedForTest {获取;设置;}
            的ObservableCollection<串GT;渠道{获取;设置;}
        }


解决方案

我将通过上下文菜单标签保留的DataContext 和隧道。

 <! - 保持完整的列表框,使所选项目的存取权限和上涨的DataContext  - >
< StackPanel的标签={绑定的RelativeSource = {的RelativeSource AncestorType =列表框}}>

 <文本菜单的DataContext ={结合PlacementTarget.DataContext,的RelativeSource = {自我的RelativeSource}}
             标签={结合PlacementTarget.Tag,的RelativeSource = {自我的RelativeSource}}>

所以,现在的的DataContext 依然是你的项目,如果你需要选择的项目使用:

Tag.SelectedItem,的RelativeSource = {的RelativeSource AncestorType =文本菜单}

Although this question is very similar to others posted, it has a few twist! I have an ObservableCollection of items in a ListBox and use a DataTemplate to display some of the collection members. However, I have a ContextMenu defined so I can execute DelegateCommands defined in my ViewModel using the Command parameter.

All my Bindings are working up to here, except that I need to provide an argument for the Command in the ViewModel using CommandParameter of the item selected in the ListBox so that the command knows which item to act upon. But this is not possible because I changed the ContextMenu DataContext so I can get at the DelegateCommands in my ViewModel.

I get the following error: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=instrumentListView'. BindingExpression:Path=SelectedItem;

The Command in the ViewModel is called as I desire, but its argument is always null.

I have also tried to Bind to items inside the collection, but they are not visible because I had to switch my DataContext.

The following is abbreviated XAML file:

            <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>

Here is a copy of my 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) {...}

        ...
}

And here is the IInstrument interface:

        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;}        
        }

解决方案

I would retain the DataContext and tunnel through the context menu tag.

<!-- 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}}">

So now the DataContext is still your item, if you need the selected item use:

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

这篇关于在将ContextMenu一个ListBox到CommandParameter绑定的SelectedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆