Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态创建上下文菜单_C#_Wpf_Xaml_Contextmenu_Menuitem - Fatal编程技术网

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>