だから私は一日中これで頭を壁にぶつけていました。
私の WPF アプリケーション (MVVM Light を使用) には、ビューモデルのコレクションにバインドされたコンテキスト メニューがあり、正しく動作していません。メニューを作成でき、MenuItems のツリーの動作、コマンドの実行、および適切なパラメーターの通過ですべてが完全に機能します。これを使用して、ユーザーがアイテムをフォルダーに追加できるコンテキスト メニューを作成しています。
私が遭遇した問題は、コンテキスト メニュー項目に子がある場合、コマンドが起動されなくなることです。したがって、子フォルダーを持たないフォルダーにのみアイテムを追加できます。
Snoop を使用してこれを調査したところ、MenuItem に対して DataContext が正しく表示され、コマンドが正しくバインドされ、mousedown イベントが発生します。
私が抱えている問題は、MenuItem に子がある場合、コマンドが実行されないことです。子を持たないアイテムの場合、コマンドは問題なく実行されます。
私はここで本当に途方に暮れており、スタック オーバーフローや MSDN ソーシャルに関する同様の質問はすべて未回答のままです。
バインディングをスタイルに設定しました。
<utility:DataContextSpy x:Key="Spy" />
<!-- Context style (in UserControl.Resources) -->
<Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="ItemsSource" Value="{Binding Children}"/>
<Setter Property="Command" Value="{Binding Command}" />
<Setter Property="CommandParameter" Value="{Binding DataContext, Source={StaticResource Spy}" />
<Setter Property="CommandTarget" Value="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</Style>
<!-- Later in the control -->
<ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}" ItemsSource="{Binding MenuItems}" />
DataSpy はこの記事からのものであり、説明どおりに機能して、usedcontrol のデータコンテキストをコマンド パラメーターとして使用できることに注意してください。
http://www.codeproject.com/Articles/27432/Artificial-Inheritance-Contexts-in-WPF
コンテキストメニューに使用されるビューモデルは次のとおりです
public interface IContextMenuItem
{
string Header { get; }
IEnumerable<IContextMenuItem> Children { get; }
ICommand Command { get; set; }
}
public class BasicContextMenuItem : ViewModelBase, IContextMenuItem
{
#region Declarations
private string _header;
private IEnumerable<IContextMenuItem> _children;
#endregion
#region Constructor
public BasicContextMenuItem(string header)
{
Header = header;
Children = new List<IContextMenuItem>();
}
#endregion
#region Observables
public string Header
{
get { return _header; }
set
{
_header = value;
RaisePropertyChanged("Header");
}
}
public IEnumerable<IContextMenuItem> Children
{
get { return _children; }
set
{
_children = value;
RaisePropertyChanged("Children");
}
}
public ICommand Command { get; set; }
#endregion
}
コンテキスト アイテムを実際に使用する方法を次に示します。
MenuItems = new List<IContextMenuItem>
{
new BasicContextMenuItem("New Folder") { Command = NewFolderCommand} ,
new BasicContextMenuItem("Delete Folder") { Command = DeleteFolderCommand },
new BasicContextMenuItem("Rename") { Command = RenameFolderCommand },
};
public ICommand NewFolderCommand
{
get { return new RelayCommand<FolderViewModel>(NewFolder); }
}
private void NewFolder(FolderViewModel viewModel)
{
// Do work
}