WPF中如何从ContextMenu命令访问CommandTarget?(无命名TextBox场景)
这个问题我之前处理过,核心原因是ContextMenu是独立的可视化元素,它并不在TextBox的可视化树结构里,所以你用RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}}的方式根本找不到目标TextBox。下面给你两种可行的解决方案:
方案一:利用ContextMenu的PlacementTarget属性
ContextMenu有个PlacementTarget属性,它指向的就是这个右键菜单附着的父控件(也就是你的TextBox)。你可以通过绑定这个属性来指定CommandTarget:
<TextBox Text="{Binding TextBoxOne, UpdateSourceTrigger=LostFocus}"> <TextBox.ContextMenu> <ContextMenu> <MenuItem Header="Set to 35" Command="{Binding SetAmountCommand}" CommandParameter="35" CommandTarget="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" /> <!-- 其他MenuItem --> </ContextMenu> </TextBox.ContextMenu> </TextBox>
这样Command就能正确作用到TextBox上了,完全不需要给TextBox命名。
方案二:直接更新ViewModel绑定属性(更符合MVVM)
如果你的项目遵循MVVM模式,其实不需要依赖CommandTarget。既然TextBox的Text已经绑定到ViewModel的TextBoxOne属性,那直接在命令里更新这个属性即可:
XAML代码:
<TextBox Text="{Binding TextBoxOne, UpdateSourceTrigger=LostFocus}"> <TextBox.ContextMenu> <ContextMenu> <MenuItem Header="Set to 35" Command="{Binding SetAmountCommand}" CommandParameter="35" /> <!-- 其他MenuItem --> </ContextMenu> </TextBox.ContextMenu> </TextBox>
ViewModel中的命令实现示例:
public ICommand SetAmountCommand => new RelayCommand<string>(param => { if (int.TryParse(param, out int amount)) { TextBoxOne = amount.ToString(); // 记得实现INotifyPropertyChanged接口,通知UI更新 } });
这种方式更简洁,也避免了可视化树绑定的问题,是MVVM场景下的推荐做法。
内容的提问来源于stack exchange,提问作者Jeson Martajaya
相关产品推荐
相关产品推荐

