C# 动态创建上下文菜单
在我的应用程序中,我希望动态构建上下文菜单。第一个C# 动态创建上下文菜单,c#,wpf,xaml,contextmenu,menuitem,C#,Wpf,Xaml,Contextmenu,Menuitem,在我的应用程序中,我希望动态构建上下文菜单。第一个菜单项是静态的,第二个菜单项应该是一个分隔符。分隔符后面的所有项目都是在运行时动态创建的 我不想使用代码隐藏,因为我正在使用MVVM模式。 我现在的想法是使用以下三种实现创建一个名为IAppMenuItem的接口 修改菜单项(静态MenuItem) 分隔项 ExecuteMenuItem(动态MenuItem 在我的应用程序的viewmodel中,我创建了一个包含上下文菜单-项的ObservableCollection 在此之前,一切正常。我
菜单项
是静态的,第二个菜单项应该是一个分隔符
。分隔符
后面的所有项目都是在运行时动态创建的
我不想使用代码隐藏,因为我正在使用MVVM模式。
我现在的想法是使用以下三种实现创建一个名为IAppMenuItem
的接口
- 修改菜单项(静态
MenuItem
)
- 分隔项
- ExecuteMenuItem(动态
MenuItem
在我的应用程序的viewmodel中,我创建了一个包含上下文菜单
-项的ObservableCollection
在此之前,一切正常。我的问题是UI中的ContextMenu
-项的显示
我试图在视图的参考资料中使用以下DataTemplate
s设置正确的控件
<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>
DataTemplate
s工作正常,但控件在MenuItem
中绘制。因此,例如对于分隔符
,我在UI中看到分隔符
-控件在MenuItem
控件中。但我需要分隔符
作为控件
有人知道如何将DataTemplate
s中的控件直接设置到contextmenu吗
更新:
完整的上下文菜单如下所示:
<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>
GenericToggleButtonStyle只是:
<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>
这是MenuItem
s的屏幕截图
在上下文菜单上设置ItemSource
属性时,似乎使用的默认itemcainer
是MenuItem
。这就是分隔符
呈现为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
样式才能获得默认的分隔符样式
这个链接为我指明了正确的方向
如何在XAML中使用自定义控件:
窗口声明:xmlns:cnt=“您的命名空间”
真的很酷。分隔符工作得很好。其他项目仍然存在问题。在另一个MenuItem
中绘制了一个MenuItem
。您可以从上下文菜单发布整个XAML吗?或者不正确的menuitems的屏幕截图吗?您可以在UI上添加不正确的menuitems
的屏幕截图吗?请参阅u解析“内部”菜单项的更新答案MenuItems
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();
}
}
}
<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>
<DataTemplate DataType="{x:Type model:ModifyMenuItem}">
<TextBlock Header="Edit items"/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:ExecuteMenuItem}">
<TextBlock Header="{Binding DisplayText}"/>
</DataTemplate>