在我的应用程序中,我想动态构建一个上下文菜单。第一个MenuItem
是静态的,第二个应该是Separator
。 Separator
之后的所有项都是在运行时动态创建的。
我不想使用代码隐藏,因为我正在使用MVVM-Pattern。
我现在的想法是使用以下三个实现来创建一个名为interface
的{{1}}
IAppMenuItem
)MenuItem
在我的应用程序的viewmodel中,我创建了一个MenuItem
,其中包含ObservableCollection<IAppMenuItem>
- 项目。
直到这里一切正常。我的问题是在UI中显示ContextMenu
- 项目。
我尝试在视图的参考资料中使用以下ContextMenu
设置正确的控件。
DataTemplate
我<DataTemplate DataType="{x:Type model:SeparatorMenuItem}">
<Separator/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ModifyMenuItem}">
<MenuItem Header="Edit items"/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ExecuteMenuItem}">
<MenuItem Header="{Binding DisplayText}"/>
</DataTemplate>
的定义只是:
ContextMenu
<ContextMenu ItemsSource="{Binding MenuItemsCollection}"/>
工作正常,但控件是在DataTemplate
内绘制的。例如,对于MenuItem
我在UI中看到Separator
- 控制Separator
- 控件。但我需要MenuItem
作为控制。
任何人都知道如何将Separator
内的控件直接设置到上下文菜单中?
更新
完整的DataTemplate
看起来像:
ContextMenu
GenericToggleButtonStyle只是:
<ToggleButton Margin="0,0,10,0"
AutomationProperties.Name="Update"
AutomationProperties.AutomationId="Update_List"
Content="Update"
AttachedProperties:ButtonExtensions.IsDropDownButton="True"
Style="{StaticResource GenericToggleButtonStyle}">
<ToggleButton.ContextMenu>
<controls:CustomContextMenu ItemsSource="{Binding MenuItemsCollection}">
<ContextMenu.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type model:ExecuteMenuItem}">
<MenuItem Header="{Binding DisplayText}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ModifyMenuItem}">
<MenuItem Header="Edit items"/>
</DataTemplate>
</ResourceDictionary>
</ContextMenu.Resources>
</controls:CustomContextMenu>
</ToggleButton.ContextMenu>
</ToggleButton>
以下是<Style x:Key="GenericToggleButtonStyle" TargetType="ToggleButton"
BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="MinWidth" Value="80" />
<Setter Property="Height" Value="22" />
<Setter Property="Padding" Value="3,1" />
</Style>
s
答案 0 :(得分:1)
似乎当您在ItemSource
上设置ContextMenu
属性时,使用的默认ItemContainer
为MenuItem
。这就是Separator
呈现为MenuItem
的原因。
您可以通过实施从ContextMenu
继承的自己的ContextMenu
控件来解决此问题。
您需要覆盖IsItemItsOwnContainerOverride
和GetContainerForItemOverride
方法。
请参阅下面的示例:
public class CustomContextMenu
: ContextMenu
{
private bool _mustGenerateAsSeparator = false;
protected override bool IsItemItsOwnContainerOverride(object item)
{
_mustGenerateAsSeparator = (item is SeparatorMenuItem);
return base.IsItemItsOwnContainerOverride(item);
}
protected override System.Windows.DependencyObject GetContainerForItemOverride()
{
if (_mustGenerateAsSeparator)
{
return new Separator { Style = this.FindResource(MenuItem.SeparatorStyleKey) as System.Windows.Style };
}
else
{
return base.GetContainerForItemOverride();
}
}
}
需要 Style = this.FindResource(MenuItem.SeparatorStyleKey) as System.Windows.Style
,因为您必须应用默认的MenuItem.SeparatorStyleKey
样式才能获得默认的分隔符样式。
此链接指向正确的方向http://drwpf.com/blog/category/item-containers/
如何在XAML中使用自定义控件:
窗口声明:xmlns:cnt="your namespace"
<Label Content="Dynamic Menu">
<Label.ContextMenu>
<cnt:CustomContextMenu x:Name="contextMenu" ItemsSource="{Binding MenuItemsCollection}">
<ContextMenu.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type model:ExecuteMenuItem}">
<MenuItem Header="{Binding DisplayText}"></MenuItem>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ModifyMenuItem}">
<MenuItem Header="{Binding DisplayText}"></MenuItem>
</DataTemplate>
</ResourceDictionary>
</ContextMenu.Resources>
</model:CustomContextMenu>
</Label.ContextMenu>
</Label>
问题的第二部分:
更新您的数据模板以使用TextBlock
,因为它们将在MenuItem
内呈现,请参阅以下内容:
<DataTemplate DataType="{x:Type model:ModifyMenuItem}">
<TextBlock Header="Edit items"/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ExecuteMenuItem}">
<TextBlock Header="{Binding DisplayText}"/>
</DataTemplate>