我希望能够将ItemsSource
的{{1}}绑定到我的视图模型中的ContextMenu
,并在{{1} },并且Collection
必须是层次结构的(层次结构的每个级别看起来都一样)。
在one of my other questions中,我设法能够在数据绑定的Separator
中显示菜单项和分隔符,但是现在我很难使ContextMenu
成为分层结构。
现在我不知道发生了什么,也许您可以启发我?
这又是我的代码(简化了一下,但是可以正常工作):
MenuItemViewModel.vb
ItemsSource
每个级别上每个菜单项的视图模型都有一个ContextMenu
显示在上下文菜单中,一个ItemsSource
标志指示它是分隔符还是功能菜单项,{{1 }}作为功能菜单项时的绑定,当然还有Public Class MenuItemViewModel
Implements ICommand
Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
Public Property IsSeparator As Boolean
Public Property Caption As String
Private ReadOnly _subItems As List(Of MenuItemViewModel)
Public Sub New(createItems As Boolean, level As Byte)
_subItems = New List(Of MenuItemViewModel)
If createItems Then
_subItems.Add(New MenuItemViewModel(level < 4, level + 1) With {.Caption = "SubItem 1"})
_subItems.Add(New MenuItemViewModel(False, level + 1) With {.IsSeparator = True, .Caption = "SubSep 1"})
_subItems.Add(New MenuItemViewModel(level < 4, level + 1) With {.Caption = "SubItem 2"})
End If
End Sub
Public ReadOnly Property SubItems As List(Of MenuItemViewModel)
Get
Return _subItems
End Get
End Property
Public ReadOnly Property Command As ICommand
Get
Return Me
End Get
End Property
Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
MessageBox.Show(Me.Caption)
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
Return True
End Function
End Class
集合,其中包含功能菜单项和分隔符,直到特定的层次结构级别。
MainViewModel.vb
Caption
主视图模型仅包含一个IsSeparator
集合,其中包含功能菜单项以及分隔符。
MainWindow.xaml
Command
窗口资源包含两个SubItems
的“ mist”和“ mict”,以及一个Public Class MainViewModel
Private ReadOnly _items As List(Of MenuItemViewModel)
Public Sub New()
_items = New List(Of MenuItemViewModel)
_items.Add(New MenuItemViewModel(True, 0) With {.Caption = "Item 1"})
_items.Add(New MenuItemViewModel(False, 0) With {.IsSeparator = True, .Caption = "Sep 1"})
_items.Add(New MenuItemViewModel(True, 0) With {.Caption = "Item 2"})
_items.Add(New MenuItemViewModel(True, 0) With {.Caption = "Item 3"})
_items.Add(New MenuItemViewModel(False, 0) With {.IsSeparator = True, .Caption = "Sep 2"})
_items.Add(New MenuItemViewModel(True, 0) With {.Caption = "Item 4"})
End Sub
Public ReadOnly Property Items As List(Of MenuItemViewModel)
Get
Return _items
End Get
End Property
End Class
“ cmics”,根据{{的值在两个Items
之间切换1}}标志。只要<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>
<ControlTemplate x:Key="mist" TargetType="{x:Type MenuItem}">
<Separator />
</ControlTemplate>
<ControlTemplate x:Key="mict" TargetType="{x:Type MenuItem}">
<MenuItem Header="{Binding Caption}" Command="{Binding Command}" ItemsSource="{Binding SubItems}" />
</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>
</Window.Resources>
<Grid>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Text="Right click me">
<TextBox.ContextMenu>
<ContextMenu ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource cmics}">
<ContextMenu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding SubItems}" />
</ContextMenu.ItemTemplate>
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</Grid>
</Window>
不分层(参见my other question),此方法就可以正常工作。
如果仅将我的ControlTemplate
“ cmics”附加到Style
的{{1}}(如我的示例代码),则它看起来像这样:
第一个级别有效,而其他级别则无效。将我的ControlTemplate
“ cmics”附加到IsSeparator
的{{1}}时,这种情况也不会改变。
如果我仅将ItemsSource
“ cmics”附加到Style
,则它看起来像这样:
第一级不显示标题和分隔符,第二级有效,而其他级别无效。
那么,如何说服ItemContainerStyle
将我的ContextMenu
“ cmics”用作每个层次结构级别的Style
?
答案 0 :(得分:1)
我找到了答案here。
我必须为分隔符创建一个空视图模型,并创建一个从ItemContainerTemplateSelector
派生的类,以返回属于菜单项类型的DataTemplate
(“ MenuItemViewModel”或“ SeparatorViewModel “)。
链接的文章应具有自我解释性。
答案 1 :(得分:0)
我只是在Xaml部分对您的(TextBox)做了一些更改。看看这个,
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Text="Right click me">
<TextBox.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding SubItems}">
<Button Content="{Binding Caption}" Command="{Binding Command}" Background="Red"/>
</HierarchicalDataTemplate>
</TextBox.Resources>
<TextBox.ContextMenu>
<ContextMenu ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource cmics}"/>
</TextBox.ContextMenu>
</TextBox>
基本上,我已删除了ContexttMenu ItemTemplate,并在TextBox下添加了。提供了一个分层数据模板。
我现在在数据模板中添加了一个单选按钮。您可以根据需要更改内容。
让我知道这是否可以解决您的问题,或者是否需要其他帮助。