C# 如何强制ContextMenu绑定自定义WPF/XAML行为?

C# 如何强制ContextMenu绑定自定义WPF/XAML行为?,c#,wpf,xaml,mvvm,asp.net-core-3.1,C#,Wpf,Xaml,Mvvm,Asp.net Core 3.1,问题: 如何访问自定义行为中分配给MenuItem的绑定命令?ContextMenu不是可视化树的一部分,只有在发生单击事件(由于在自定义行为中被抑制而从未发生)时才会绑定 目的 我有一个使用Microsoft.Xaml.Behaviors的自定义行为,该行为仅用于在用户单击ListView中的对象时显示上下文菜单。我想在访问视图标记中的引用ICommand时使用自定义行为修改命令参数 代码: 自定义行为(Microsoft.Xaml.Behaviors): public类右键单击上下文菜单行为

问题: 如何访问自定义行为中分配给MenuItem的绑定命令?ContextMenu不是可视化树的一部分,只有在发生单击事件(由于在自定义行为中被抑制而从未发生)时才会绑定

目的 我有一个使用Microsoft.Xaml.Behaviors的自定义行为,该行为仅用于在用户单击ListView中的对象时显示上下文菜单。我想在访问视图标记中的引用ICommand时使用自定义行为修改命令参数

代码:

自定义行为(Microsoft.Xaml.Behaviors):

public类右键单击上下文菜单行为:行为
{
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.ContextMenuOpening+=AssociatedObject\u ContextMenuOpening;
AssociatedObject.PreviewMouseRightButtonDown+=AssociatedObject\u PreviewMouseRightButtonDown;
AssociatedObject.PreviewMouseRightButtonUp+=AssociatedObject\u PreviewMouseRightButtonUp;
}
受保护的覆盖无效OnDetached()
{
base.OnDetached();
AssociatedObject.ContextMenuOpening-=AssociatedObject\u ContextMenuOpening;
AssociatedObject.PreviewMouseRightButtonDown-=
关联对象\u预览鼠标右键向下;
AssociatedObject.PreviewMouseRightButtonUp-=AssociatedObject\u PreviewMouseRightButtonUp;
}
私有无效关联对象\u预览鼠标右键向下(对象发送者,鼠标按钮目标)
{
//存储单击位置,以便确定鼠标移动时的拖动。
原点=e.GetPosition(空);
//从ListView中获取项目
var listViewItem=TryFindFromPoint((UIElement)发送方,
e、 GetPosition(关联对象));
如果(listViewItem==null)
返回;
itemReference=listViewItem;
}
private void Associated object_PreviewMouseRightButtonUp(对象发送方,
鼠标按钮(文塔)
{
if(itemReference!=null)
{
//仅当用户单击对象时才显示关联菜单
//在listview内部,而不是listview本身。
var targetPosition=e.GetPosition((UIElement)itemReference);
HitTestResult hitResult=VisualTreeHelper.HitTest((UIElement)itemReference,
目标位置);
如果(hitResult!=null&&sender为ListView)
{
var listView=发送方作为listView;
//设置上下文菜单的可见性标志
listView.ContextMenu.IsOpen=true;
foreach(listView.ContextMenu.Items中的变量项)
{
如果(项目为菜单项)
{
var customMemuItem=作为菜单项的项目;
//将hitbox中的项目作为上下文应用。
customMemuItem.CommandParameter=itemReference.DataContext;
/*
问题:
这里的绑定总是空的,如何强制绑定
XAML标记中的ICommand将在此处可用。我希望
使用标记中的命令绑定,以及
应用我的DataContext customMemuItem。命令为空
*/
}
}
e、 Handled=true;//处理气泡
}
}
其他的
{
如果(发件人是ListView)
{
//隐藏关联菜单。
var listView=发送方作为listView;
listView.ContextMenu.IsOpen=false;
e、 已处理=正确;
}
}
}
}
查看:


[...]
编辑#1: 我们在ListView所在的位置使用MVVM:

public partial class MyViewModelView : UserControl
{
    public DocumentTileManagementView()
    {
        InitializeComponent();
    }
}
public class MyViewModel : ViewModelBase
{
    public MyViewModel()
    {
        MenuTestCommand = new ApplicationRelayCommand(MenuTestCommandBehavior);
    }


    public ObservableCollection<ObjectViewModel> ItemQueue
    {
        get
        {
            return _ItemQueue;
        }
        set
        {
            this.MutateVerbose(ref _ItemQueue, value, this.RaisePropertyChanged());
        }
    }
    private ObservableCollection<MyDataObject> _ItemQueue= new ObservableCollection<MyDataObject>();
   
    public ICommand MenuTestCommand { get; }
    private async void MenuTestCommandBehavior(object obj)
    {

    }
}
公共部分类MyViewModelView:UserControl { 公共文档TileManagementView() { 初始化组件(); } } 公共类MyViewModel:ViewModelBase { 公共MyViewModel() { MenuTestCommand=new ApplicationRelayCommand(MenuTestCommandBehavior); } 公共ObservableCollection项队列 { 得到 { 返回_ItemQueue; } 设置 { this.MutateVerbose(ref _ItemQueue,value,this.RaisePropertyChanged()); } } 私有ObservableCollection_ItemQueue=新ObservableCollection(); public ICommand menutest命令{get;} 私有异步void菜单TestCommandBehavior(对象obj) { } } 我还没有找到一种在不允许ListView上的初始右键单击事件链的情况下调用绑定的方法


我有一个可行的解决方案,允许第一次右键单击事件,并在随后的每次单击中覆盖该行为。我想在自定义(Microsoft.Xaml.Behaviors)行为中调用第一次右键单击期间发生的任何事件。

而不是试图覆盖我附加到
ContextMenuOpening
事件的整个事件链。在第一个
PreviewMouseRightButtonUp
中,我们允许事件链完成标记中所有参数和命令的绑定。
ContextMenuOpening
事件允许初始hitbox配置和
CommandParameter
分配

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.ContextMenuOpening += AssociatedObject_ContextMenuOpening;
        [...]  
    }

    private void AssociatedObject_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (!isFirstClick)
        {
            isFirstClick = true;
            e.Handled = false;
            AssociatedObject.ContextMenu.Visibility = Visibility.Collapsed;
            return;
        }
        else 
        {
            [...]        
        }
    }
    private void AssociatedObject_ContextMenuOpening(object sender, ContextMenuEventArgs e)
    {
        if (AssociatedObject.Items.Count > 0)
        {
            var listViewItem = TryFindFromPoint<ListViewItem>((UIElement)e.OriginalSource, new Point(e.CursorLeft, e.CursorTop));
            foreach (var item in AssociatedObject.ContextMenu.Items)
            {
                if (item is MenuItem && listViewItem != null)
                {
                    var customMemuItem = item as MenuItem;
                    customMemuItem.CommandParameter = listViewItem.DataContext;
                }
            }
            AssociatedObject.ContextMenu.Visibility = Visibility.Visible;
            AssociatedObject.ContextMenu.IsOpen = true;
        }
        else
        {
            AssociatedObject.ContextMenu.Visibility = Visibility.Collapsed;
            AssociatedObject.ContextMenu.IsOpen = false;
        }
    }

protected override void OnAttached()
{
base.onatached();
AssociatedObject.ContextMenuOpening+=AssociatedObject\u ContextMenuOpening;
[...]  
}
private void Associated object_PreviewMouseRightButtonUp(对象发送器,鼠标按钮Ventargs e)
{
如果(!isFirstC