ContextMenu с ItemsSource и разделителями - PullRequest
0 голосов
/ 23 мая 2019

Я бы хотел связать ItemsSource из ContextMenu с коллекцией в моей модели представления, и я бы хотел, чтобы ContextMenu также показывал Separator с.

Обычно Separator в ContextMenu отображается как горизонтальная линия. Но это не работает в моем случае. Может быть, вы можете пролить свет на это?

Я знаю, что модели представлений должны реализовывать INotifyPropertyChanged, но для простоты я отбросил свой пример всего ненужного.

MenuItemViewModel.vb:

Public Class MenuItemViewModel
    Public Property IsSeparator As Boolean
    Public Property Caption As String
End Class

MainViewModel.vb:

Public Class MainViewModel
    Private ReadOnly _items As List(Of MenuItemViewModel)

    Public Sub New()
        _items = New List(Of MenuItemViewModel)
        _items.Add(New MenuItemViewModel With {.Caption = "Item 1"})
        _items.Add(New MenuItemViewModel With {.IsSeparator = True, .Caption = "Sep 1"})
        _items.Add(New MenuItemViewModel With {.Caption = "Item 2"})
        _items.Add(New MenuItemViewModel With {.Caption = "Item 3"})
        _items.Add(New MenuItemViewModel With {.IsSeparator = True, .Caption = "Sep 2"})
        _items.Add(New MenuItemViewModel With {.Caption = "Item 4"})
    End Sub

    Public ReadOnly Property Items As List(Of MenuItemViewModel)
        Get
            Return _items
        End Get
    End Property
End Class

MenuItemTemplateSelector.vb:

Public Class MenuItemTemplateSelector
    Inherits DataTemplateSelector

    Public Property ItemTemplate As DataTemplate
    Public Property SeparatorTemplate As DataTemplate

    Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
        Dim menuItem As MenuItemViewModel

        menuItem = TryCast(item, MenuItemViewModel)

        If (menuItem IsNot Nothing) AndAlso menuItem.IsSeparator Then
            Return Me.SeparatorTemplate
        Else
            Return Me.ItemTemplate
        End If
    End Function
End Class

MainWindow.xaml:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
    d:DataContext="{d:DesignInstance local:MainViewModel, IsDesignTimeCreatable=True}"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>

    <Window.Resources>
        <DataTemplate x:Key="mit">
            <TextBlock Text="{Binding Caption}" />
        </DataTemplate>

        <DataTemplate x:Key="mst">
            <Separator />
            <!--<Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}" />-->
        </DataTemplate>

        <local:MenuItemTemplateSelector x:Key="mits"
                                        ItemTemplate="{StaticResource mit}"
                                        SeparatorTemplate="{StaticResource mst}" />

    </Window.Resources>

    <Grid>
        <TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Text="Right click me">
            <TextBox.ContextMenu>
                <ContextMenu ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource mits}" />
            </TextBox.ContextMenu>
        </TextBox>
    </Grid>
</Window>

Если вы щелкнете правой кнопкой мыши по TextBox, всплывет ContextMenu, но Separator не будут отображаться как горизонтальные линии, вместо этого они выглядят как обычные пункты меню, но без заголовка. Они даже синего цвета, когда мышь парит над ними.

Поскольку у них есть заголовок в модели представления, и этот заголовок не отображается, кажется, что он действительно не использует определенный ItemTemplate, но какой шаблон он использует? Или простой <Separator /> больше не создает горизонтальную линию?)

Как я могу получить разделитель по умолчанию, чтобы показать?


Редактировать: Кажется, что мой Separator обернут внутри MenuItem, но как мне этого избежать?

1 Ответ

0 голосов
/ 24 мая 2019

После комментария Ed Plunkett я избавился от файла "MenuItemTemplateSelector.vb" и всех соответствующих ресурсов окна ("mit", "mst" и "mits").

Затем я добавил следующие новые ресурсы окна ...

<ControlTemplate x:Key="mist" TargetType="{x:Type MenuItem}">
    <Separator />
</ControlTemplate>

<ControlTemplate x:Key="mict" TargetType="{x:Type MenuItem}">
    <MenuItem Header="{Binding Caption}" />
</ControlTemplate>

<Style x:Key="cmics" TargetType="{x:Type MenuItem}">
    <Setter Property="Template" Value="{StaticResource mict}" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsSeparator}" Value="True">
            <Setter Property="Template" Value="{StaticResource mist}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

... и изменил мой TextBox на ...

<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Text="Right click me">
    <TextBox.ContextMenu>
        <ContextMenu ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource cmics}" />
    </TextBox.ContextMenu>
</TextBox>

... и все отлично работает.

Спасибо Эд Планкетт .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...