基于数据模板的上下文菜单项的不同格式
Different formatting on context menu items based on data template
我有一个可用的动态上下文菜单,但 XAML 格式似乎有问题。对我来说,似乎第一个选择的模板将用于所有菜单项。
我希望将图标放置在左侧突出显示列的正常标准位置,我仍然可以自定义右侧 XAML- 分别为每个菜单项定义的内容在他们的 DataTemplate
.
这里是 XAML 代码片段,与 ListBox
一起使用
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding ModelContextMenu}"
ItemTemplateSelector="{StaticResource ContextMenuItemDataTemplateSelector}">
</ContextMenu>
</ListBox.ContextMenu>
以及不同菜单项的数据模板:
<DataTemplate x:Key="ChangeColorMenuItem" DataType="MenuItem">
<DockPanel>
<MenuItem Header="{Binding DisplayName}"
Command="{Binding Command}">
</MenuItem>
<xctk:ColorPicker
SelectedColor="{Binding DataContext.SelectedColor, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:View}}}"
Margin="0,0,0,0" />
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="NormalMenuItem" DataType="MenuItem">
<MenuItem Header="{Binding DisplayName}"
Command="{Binding Command}">
<MenuItem.Icon>
<Image Source="{Binding Icon}"/>
</MenuItem.Icon>
</MenuItem>
</DataTemplate>
最后是模板选择器 class:
public class ContextMenuItemDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (container is FrameworkElement element && item is ContextMenuCommand commandItem)
{
switch (commandItem.MenuType)
{
case ContextMenuType.Normal:
return
element.FindResource("NormalMenuItem") as DataTemplate;
case ContextMenuType.ChangeColor:
return
element.FindResource("ChangeColorMenuItem") as DataTemplate;
default:
throw new ArgumentOutOfRangeException();
}
}
return null;
}
}
编辑 1
每个 MenuItem
内容都封装在绑定到 ContextMenu
的列表中。集合中的对象确实包含每个 MenuItem
的所有数据,例如图标、显示名称和 ICommand
.
public ObservableCollection<ContextMenuCommand> ModelContextMenu => _selectedModel.Commands;
编辑 2
在下图中用蓝色十字标记的所需(标准)图标位置:
问题似乎是两个内部 MenuItem
因为有问题的数据模板。
通过按以下方式定义 ItemTemplate
和自定义 ItemContainerStyle
解决了该问题:
DataTemplates
<DataTemplate x:Key="ChangeColorMenuItem" DataType="MenuItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding DisplayName}"
Padding="5,0,5,0"/>
<xctk:ColorPicker Grid.Column="1"
SelectedColor="{Binding DataContext.SelectedEntityColor, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PanelView}}}"
Margin="0,0,0,0" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="NormalMenuItem" DataType="MenuItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding DisplayName}" />
</Grid>
</DataTemplate>
列表框上下文菜单
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CadModelContextMenu}"
ItemTemplateSelector="{StaticResource PanelContextMenuItemDataTemplateSelector}"
UsesItemContainerTemplate="True">
<ContextMenu.Resources>
<ResourceDictionary>
<Image x:Key="menuIcon" x:Shared="false"
Source="{Binding Path=Icon}" Height="16px" Width="16px"/>
</ResourceDictionary>
</ContextMenu.Resources>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon" Value="{StaticResource menuIcon}"/>
<Setter Property="Command" Value="{Binding Command}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</ListBox.ContextMenu>
此解决方案的图标因每个项目而异。图标在底层对象的 属性 中定义。
我有一个可用的动态上下文菜单,但 XAML 格式似乎有问题。对我来说,似乎第一个选择的模板将用于所有菜单项。
我希望将图标放置在左侧突出显示列的正常标准位置,我仍然可以自定义右侧 XAML- 分别为每个菜单项定义的内容在他们的 DataTemplate
.
这里是 XAML 代码片段,与 ListBox
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding ModelContextMenu}"
ItemTemplateSelector="{StaticResource ContextMenuItemDataTemplateSelector}">
</ContextMenu>
</ListBox.ContextMenu>
以及不同菜单项的数据模板:
<DataTemplate x:Key="ChangeColorMenuItem" DataType="MenuItem">
<DockPanel>
<MenuItem Header="{Binding DisplayName}"
Command="{Binding Command}">
</MenuItem>
<xctk:ColorPicker
SelectedColor="{Binding DataContext.SelectedColor, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:View}}}"
Margin="0,0,0,0" />
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="NormalMenuItem" DataType="MenuItem">
<MenuItem Header="{Binding DisplayName}"
Command="{Binding Command}">
<MenuItem.Icon>
<Image Source="{Binding Icon}"/>
</MenuItem.Icon>
</MenuItem>
</DataTemplate>
最后是模板选择器 class:
public class ContextMenuItemDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (container is FrameworkElement element && item is ContextMenuCommand commandItem)
{
switch (commandItem.MenuType)
{
case ContextMenuType.Normal:
return
element.FindResource("NormalMenuItem") as DataTemplate;
case ContextMenuType.ChangeColor:
return
element.FindResource("ChangeColorMenuItem") as DataTemplate;
default:
throw new ArgumentOutOfRangeException();
}
}
return null;
}
}
编辑 1
每个 MenuItem
内容都封装在绑定到 ContextMenu
的列表中。集合中的对象确实包含每个 MenuItem
的所有数据,例如图标、显示名称和 ICommand
.
public ObservableCollection<ContextMenuCommand> ModelContextMenu => _selectedModel.Commands;
编辑 2
在下图中用蓝色十字标记的所需(标准)图标位置:
问题似乎是两个内部 MenuItem
因为有问题的数据模板。
通过按以下方式定义 ItemTemplate
和自定义 ItemContainerStyle
解决了该问题:
DataTemplates
<DataTemplate x:Key="ChangeColorMenuItem" DataType="MenuItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding DisplayName}"
Padding="5,0,5,0"/>
<xctk:ColorPicker Grid.Column="1"
SelectedColor="{Binding DataContext.SelectedEntityColor, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PanelView}}}"
Margin="0,0,0,0" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="NormalMenuItem" DataType="MenuItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding DisplayName}" />
</Grid>
</DataTemplate>
列表框上下文菜单
<ListBox.ContextMenu>
<ContextMenu ItemsSource="{Binding CadModelContextMenu}"
ItemTemplateSelector="{StaticResource PanelContextMenuItemDataTemplateSelector}"
UsesItemContainerTemplate="True">
<ContextMenu.Resources>
<ResourceDictionary>
<Image x:Key="menuIcon" x:Shared="false"
Source="{Binding Path=Icon}" Height="16px" Width="16px"/>
</ResourceDictionary>
</ContextMenu.Resources>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon" Value="{StaticResource menuIcon}"/>
<Setter Property="Command" Value="{Binding Command}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</ListBox.ContextMenu>
此解决方案的图标因每个项目而异。图标在底层对象的 属性 中定义。