wpf - 为什么数据绑定(bind)上下文菜单项不隐藏?

标签 wpf data-binding contextmenu menuitem

我不想使用数据绑定(bind)对象的某些属性在上下文菜单中隐藏/显示菜单项。 但我的菜单项没有隐藏,它们的行为就好像它们的 Visibility 将设置为 Visibility.Hidden (而不是 Visibility.Collapsed,因为它实际上是),这种行为的原因是什么?

这是一个例子:

XAML:

<Window x:Class="MenuTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="converter"/>
        <DataTemplate x:Key="template">            
            <MenuItem Visibility="{Binding Visible, Converter={StaticResource converter}}" Header="{Binding Title}" />
        </DataTemplate>
        <ContextMenu x:Key="menu" ItemTemplate="{StaticResource template}"/>                    
    </Window.Resources>
    <Grid>
        <Button VerticalAlignment="Center" HorizontalAlignment="Center" Click="OnClick">Button</Button>
    </Grid>
</Window>

以及背后的代码:

public partial class Window1 : Window
    {
        public ObservableCollection<Item> list = new ObservableCollection<Item>();
        public Window1()
        {
            InitializeComponent();
            list.Add(new Item() { Title = "First", Visible = true }); ;
            list.Add(new Item() { Title = "Second", Visible = false }); ;
            list.Add(new Item() { Title = "Third", Visible = false }); ;
            list.Add(new Item() { Title = "Fourth", Visible = true }); ;
        }

        private void OnClick(object sender, RoutedEventArgs e)
        {
            ContextMenu cm =  FindResource("menu") as ContextMenu;
            cm.PlacementTarget = e.OriginalSource as UIElement;
            cm.Placement = System.Windows.Controls.Primitives.PlacementMode.Left;
            cm.ItemsSource = list;
            cm.IsOpen = true;
        }
    }

    public class Item
    {
        public string Title { get; set; }
        public bool Visible { get; set; }
    }

结果是包含四个项目的菜单(但中间有两个项目,标题中没有任何可见文本)。

最佳答案

此行为是因为 ContextMenu 的 ItemTemplate 将应用于为该 Item 创建的 MenuItem 内的每个绑定(bind) Item。通过将 MenuItem 放入 DataTemplate 中,您可以创建一个嵌套的 MenuItem。即使你折叠了里面的,因为外面的仍然可见,所以仍然有空间。

您可以通过删除 DataTemplate 中的嵌套 MenuItem 并将其替换为 TextBlock,并使用适用于 MenuItem 的样式来设置可见性来解决此问题:

<Window x:Class="MenuTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="converter"/>
        <DataTemplate x:Key="template">
            <TextBlock Text="{Binding Title}"/>
        </DataTemplate>
        <ContextMenu x:Key="menu" ItemTemplate="{StaticResource template}">
            <ContextMenu.Resources>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Visibility" Value="{Binding Visible, Converter={StaticResource converter}}"/>
                </Style>
            </ContextMenu.Resources>
        </ContextMenu>
    </Window.Resources>
    <Grid>
        <Button HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnClick">Button</Button>
    </Grid>
</Window>

关于wpf - 为什么数据绑定(bind)上下文菜单项不隐藏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/376121/

相关文章:

node.js - 将选项与 Electron 集成到资源管理器上下文菜单中

angular - 防止angular7中的默认上下文菜单

c# - 无法使用 Prism.Mvvm.ViewModelLocationProvider 手动将 View 注册到 ViewModel

.net - 使用 IMultiValueConverter 将多个 CommandParameters 传递给 viewModel

c# - 将 CheckedListBox 绑定(bind)到设置

java - 从 EntityManager 获取所有映射的实体

.net - WPF - 数据绑定(bind)到同一控件的属性

c# - WPF 选项卡顺序工作错误

javascript - 输入上的 v-model 返回输入元素而不是值

swift - 如何知道在(iOS 13+)configurationForMenuAtLocation 上为上下文菜单触发了哪个 UICollectionView 单元格