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