WPF/Caliburn Micro中按钮触发的ContextMenu无法设置DataContext问题
问题分析
ContextMenu属于弹出式元素,不在控件的视觉树(VisualTree)中,默认无法继承父控件(Button)的DataContext,导致Caliburn.Micro无法找到HomeViewModel中的SignOutClick方法。
解决方案
方法1:直接绑定ContextMenu的DataContext到触发控件的DataContext
修改XAML中ContextMenu的定义,去掉冗余的Tag和cal:Action.TargetWithoutContext,直接将ContextMenu的DataContext绑定到Button的DataContext:
<Button x:Name="cogButton" Grid.Column="2" BorderThickness="0" Background="White"> <Button.ContextMenu> <ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> <MenuItem Header="Sign Out" cal:Message.Attach="SignOutClick($dataContext)" /> </ContextMenu> </Button.ContextMenu> <Image Source="/Images/TrayCogIcon.png"> <i:Interaction.Triggers> <i:EventTrigger SourceName="cogButton" EventName="Click"> <cal:ActionMessage MethodName="CogButtonClick"> <cal:Parameter Value="{Binding ElementName=cogButton}" /> </cal:ActionMessage> </i:EventTrigger> </i:Interaction.Triggers> </Image> </Button>
这里PlacementTarget指向触发ContextMenu的Button,PlacementTarget.DataContext就是HomeViewModel,MenuItem的绑定会直接关联到ViewModel中的方法。
方法2:修正cal:Action.TargetWithoutContext的绑定路径
如果需要保留cal:Action.TargetWithoutContext的用法,直接绑定到Button的DataContext即可,无需通过Tag中转:
<Button x:Name="cogButton" Grid.Column="2" BorderThickness="0" Background="White"> <Button.ContextMenu> <ContextMenu cal:Action.TargetWithoutContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> <MenuItem Header="Sign Out" cal:Message.Attach="SignOutClick($dataContext)" /> </ContextMenu> </Button.ContextMenu> <Image Source="/Images/TrayCogIcon.png"> <i:Interaction.Triggers> <i:EventTrigger SourceName="cogButton" EventName="Click"> <cal:ActionMessage MethodName="CogButtonClick"> <cal:Parameter Value="{Binding ElementName=cogButton}" /> </cal:ActionMessage> </i:EventTrigger> </i:Interaction.Triggers> </Image> </Button>
该写法会明确告知Caliburn.Micro,Action的目标对象是Button的DataContext(即HomeViewModel)。
补充说明
- 你的
SignOutClick方法参数为object sender,当前用$dataContext传递的是ViewModel实例;若需要传递MenuItem本身或事件参数,可替换为$source或$eventArgs。 - 确保XAML中已正确引入Caliburn.Micro命名空间:
xmlns:cal="http://www.caliburnproject.org"
内容的提问来源于stack exchange,提问作者jwright755
相关产品推荐
相关产品推荐

