Почему элементы ContextMenu с привязкой к данным не скрываются?

StackOverflow https://stackoverflow.com/questions/376121

Вопрос

Я не хочу скрывать/показывать элементы меню в контекстном меню, используя какое-либо свойство объекта с привязкой к данным.Но мои пункты меню не скрываются, они ведут себя так, как если бы для их видимости было установлено значение Visibility.Hidden (а не Visibility.Collapsed, как это есть на самом деле), в чем причина такого поведения?

Вот пример:

КСАМЛ:

<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; }
    }

В результате получается меню с четырьмя пунктами (но два посередине без видимого текста в заголовке).

Это было полезно?

Решение

Такое поведение связано с тем, что ItemTemplate ContextMenu будет применяться к каждому из ваших связанных элементов. в пределах MenuItem, созданный для этого элемента.Помещая MenuItem в свой DataTemplate, вы создаете вложенный MenuItem.Даже если свернуть внутренний, поскольку внешний все равно виден, для него еще останется место.

Вы можете исправить это, избавившись от вложенного MenuItem в вашем DataTemplate и заменив его 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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top