绑定更改后会弹出WPF上下文菜单



我在UserControl中有一个Border控件,它用作图形更改的开关。Border有一个上下文菜单,包含两个MenuItems:"打开"one_answers"关闭"。

当开关闭合时,只有"打开"MenuItem可见,而当开关打开时只有"关闭"可见。对于某些开关,我需要完全禁用"打开"或"关闭",所以我不希望它们在任何时候都可见。这是代码:

<Border.ContextMenu>
<ContextMenu Name="switchContextMenu">
<ContextMenu.Visibility>
<MultiBinding Converter="{StaticResource ContextMenuBoolToVisibility}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</ContextMenu.Visibility>
<MenuItem Name="miOpen" Header="{Binding Path=Resources.PowerControlSystem_OPEN, Source={StaticResource LocalizedStrings} }" 
Click="miOpen_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
<MenuItem Name="miClose" Header="{Binding Path=Resources.PowerControlSystem_CLOSE, Source={StaticResource LocalizedStrings} }" 
Click="miClose_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
</ContextMenu>
</Border.ContextMenu>

我将此开关用作通用组件,因此在另一个.xml代码中,我设置了"Open Available"one_answers"Close Available"属性。这是我的问题:

我有一个开关,其"打开可用"属性设置为False。默认情况下,此开关处于打开状态。我可以关闭它,这没关系。然后当我再次右键单击此开关时,上下文菜单将不可见。这也可以。

问题是,当我更改一些值时,这个开关再次打开,此时,上下文菜单弹出。我认为问题出在上下文菜单可见性的转换器中。此时会触发它,并且ContextMenu变为可见。

有人知道如何制止这种行为吗?

您可以设置Border样式,而不是设置ContextMenu可见性

<Border>
<Border.Style>
<Style TargetType="Border">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Name="switchContextMenu">
<MenuItem Name="miOpen" Header="{Binding Path=Resources.PowerControlSystem_OPEN, Source={StaticResource LocalizedStrings} }" 
Click="miOpen_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
<MenuItem Name="miClose" Header="{Binding Path=Resources.PowerControlSystem_CLOSE, Source={StaticResource LocalizedStrings} }" 
Click="miClose_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ContextMenuBoolAggregate}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>

因此,触发器是有条件地移除ContextMenu,而不是更改其可见性。我使用ContextMenuBoolAggregate转换器名称来指示您需要创建一个新的转换器,该转换器正在确定删除上下文菜单的正确值——我认为如何实现该部分是很清楚的。

如果你的条件足够简单,你可以使用MultiDataTrigger而不是DataTrigger以及MultiBindingConverter:

<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding OpenAvailable}" Value="False"/>
<Condition Binding="{Binding OpenVisible}" Value="False"/>
<Condition Binding="{Binding CloseAvailable}" Value="False"/>
<Condition Binding="{Binding CloseVisible}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</MultiDataTrigger>

我用另一种方式找到了解决方案。我使用了ContextMenuService.IsEnabled属性。当设置为false时,上下文菜单将无法显示。所以,我在我的Border.xaml代码中添加了这个:

<ContextMenuService.IsEnabled>
<MultiBinding Converter="{StaticResource ContextMenuBoolToVisibility}">
<Binding Path="OpenAvailable" ElementName="mySwitch" />
<Binding Path="OpenVisible" ElementName="mySwitch" />
<Binding Path="CloseAvailable" ElementName="mySwitch" />
<Binding Path="CloseVisible" ElementName="mySwitch" />
</MultiBinding>
</ContextMenuService.IsEnabled>

我还更换了ContextMenuBoolToVisibility转换器。现在不再返回Visibility.VisibleVisibility.Collapsed,而是为ContextMenuService.IsEnabled属性返回truefalse