この質問は他の投稿と非常によく似ていますが、少しひねりがあります。ListBoxにアイテムのObservableCollectionがあり、 DataTemplateを使用してコレクションメンバーの一部を表示しています。ただし、ContextMenuを定義しているので、 Commandパラメーターを使用してViewModelで定義されたDelegateCommandsを実行できます。
リストボックスで選択されたアイテムのCommandParameterを使用してViewModelでコマンドの引数を指定し、コマンドがどのアイテムに作用するかを認識できるようにする必要があることを除いて、すべてのバインディングはここまで機能しています。ただし、ViewModelのDelegateCommandsを取得できるように、ContextMenu DataContextを変更したため、これは不可能です。
次のエラーが発生します:System.Windows.Dataエラー:4:参照'ElementName=instrumentListView'でバインドするためのソースが見つかりません。BindingExpression:Path = SelectedItem;
ViewModelのコマンドは私が望むように呼び出されますが、その引数は常に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;}
}