如何在无子项时隐藏MenuItem且避免重复计算AvailableMacros
解决方案
要避免AvailableMacros被重复计算,同时在无可用子项时隐藏父MenuItem,可以利用WPF控件的内置属性结合多值绑定来实现,核心思路是复用ItemsSource绑定后的结果,而非重复触发属性计算。
方案:多值绑定 + 自定义转换器
利用MenuItem的HasItems属性(该属性会自动根据ItemsSource的内容判断是否存在子项,不会重复触发AvailableMacros的计算),结合原有的SetToSpecificMacroCommand可见性条件,通过多值绑定统一控制Visibility。
步骤1:创建多值转换器
实现一个IMultiValueConverter,同时判断命令是否有效、是否存在子项,返回对应的可见性:
public class CommandAndHasItemsToVisibilityConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { // 第一个绑定值:SetToSpecificMacroCommand var isValidCommand = values[0] is ICommand; // 第二个绑定值:MenuItem的HasItems属性 var hasItems = values[1] is bool hasItemsBool && hasItemsBool; return isValidCommand && hasItems ? Visibility.Visible : Visibility.Collapsed; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
步骤2:在XAML中声明转换器资源
将转换器添加到资源字典中(比如Window/UserControl的Resources节点):
<local:CommandAndHasItemsToVisibilityConverter x:Key="CommandAndHasItemsToVisibilityConverter"/>
步骤3:修改MenuItem的Visibility绑定
将原有的单值绑定替换为多值绑定,同时绑定命令和当前MenuItem的HasItems属性:
<MenuItem Header="{x:Static res:Strings.SetToSpecificMacro}" ItemsSource="{Binding AvailableMacros}"> <MenuItem.Visibility> <MultiBinding Converter="{StaticResource CommandAndHasItemsToVisibilityConverter}"> <!-- 原有的命令绑定条件 --> <Binding Path="SetToSpecificMacroCommand"/> <!-- 绑定当前MenuItem的HasItems属性,复用ItemsSource的结果 --> <Binding RelativeSource="{RelativeSource Self}" Path="HasItems"/> </MultiBinding> </MenuItem.Visibility> <MenuItem.ItemContainerStyle> <Style TargetType="{x:Type MenuItem}"> <Setter Property="Header" Value="{Binding Key}" /> <Setter Property="Command" Value="{Binding Command}" /> <Setter Property="CommandParameter" Value="{Binding Key}" /> </Style> </MenuItem.ItemContainerStyle> <MenuItem.Icon> <Image Source="/Resources/Images/Icons/PlaceMacro16.png" /> </MenuItem.Icon> </MenuItem>
为什么不会重复计算AvailableMacros?
当菜单打开时,ItemsSource="{Binding AvailableMacros}"会触发一次AvailableMacros的计算,MenuItem会枚举该集合来创建子项,同时自动更新自身的HasItems属性。多值绑定中的HasItems绑定仅读取这个已计算的结果,不会再次调用AvailableMacros的getter,因此只会触发一次属性计算,完全避免了性能损耗。
内容的提问来源于stack exchange,提问作者Spook
相关产品推荐
相关产品推荐

