Extend/Merge/Share Context Menus from custom control - wpf

I use a custom control in multiple views. In that custom control I defined a context menu with common MenuItems, that need to be available in different views. Each view than can extend that context menu by their own MenuItems.
How do I accomplish this? I can only replace the exsting context menu, but not extending it.
I read about merging context menus here: http://wpftutorial.net/ContextMenu.html.
But it doesn't show how to merge with the existing ones.

Use resources. You define all the menu items in the window/usercontrol's resource, and then reference them with the key of the menu items.
<Window.Resources>
<MenuItem Header="Add sub-folder"
Command="{Binding FolderNewCmd}"
x:Key="AddFolderMenu">
<MenuItem.Icon>
<Image Source="/YourAssemblyNameSpace;component/Images/16/abc.png"
Width="16"
RenderOptions.BitmapScalingMode="NearestNeighbor">
</Image>
</MenuItem.Icon>
</MenuItem>
... <--other menu items-->
<Window.Resources>
When you want to reference this menu item in a menu (e.g. a context menu):
<TreeView.ContextMenu>
<StaticResource ResourceKey="AddFolderMenu" />
<StaticResource ResourceKey="OtherMenuItemInResource" />
...
</TreeView.ContextMenu>

Related

Using a user control as a context menu in WPF

I've created a WPF user control that contains some grids, buttons, and sliders. I'd like to use this control as (or in place of) a context menu in my main application window. When a user right-clicks the mouse button, I'd like my user control to be displayed, rather than a normal looking context menu with standard menu items.
What's the best approach to take in displaying a user defined WPF control in place of a context menu?
You could define the ControlTemplate of a ContextMenu however you want. Try this:
<Window ... xmlns:local="clr-namespace:WpfApplication1">
<Grid Background="Transparent">
<StackPanel.ContextMenu>
<ContextMenu>
<ContextMenu.Template>
<ControlTemplate TargetType="ContextMenu">
<local:UserControl1 />
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</StackPanel.ContextMenu>
Just add the control to the ContextMenu. For example:
<Window>
<Window.ContextMenu>
<ContextMenu>
<local:YourUserControl />
</ContextMenu>
</Window.ContextMenu>
</Window>

How to create vertical menu control in WPF

Iam trying to create vertical menu control but dont know from where to start. I am basically coming from winform to wpf and using telerik controls and this control which am using is called RadMenuControl.
Please view the video in link and suggest me accordingly with code and helping links from where i can start, thanks in advance.
MenuItem Video
You can change the ItemsPanel of Menu control.
Inheritance heirarchy :
ItemsControl > MenuBase > Menu.
<Menu Height="Auto" Width="Auto" FontSize="18">
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</Menu.ItemsPanel>
<MenuItem Header="Styling">
<MenuItem Header="Background"/>
</MenuItem>
<MenuItem Header="Measurement">
<MenuItem Header="Width"/>
<MenuItem Header="Height"/>
</MenuItem>
<MenuItem Header="Font"/>
</Menu>
If you need an similar functionality, you may consider using a StackPanel and keep stacking button items to them.
<StackPanel>
<Button Content="Home"/>
<Button Content="Edit"/>
<Button Content="View"/>
</StackPanel>
If you are using Telerik controls would you try RadPanelBar or RadOutlookBar. Surely your requirement will be satisfied one of these two controls.
RadPanelBar

Xceed splitbutton with menu items and sub menuitems

I`m trying to have a dropdown menu under a split button. Some of these menuItems should have sub-menu items. If you want an example, click on the bookmark button in Firefox (top right).
I can't use Menu, because that is always oriented horizontally. So I went with a stackpanel:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" Height="350" Width="525">
<Grid>
<xctk:SplitButton Content="SplitButton" BorderThickness="1" BorderBrush="Black" Margin="0,0,408,290">
<xctk:SplitButton.DropDownContent>
<StackPanel Width="161" HorizontalAlignment="Left">
<MenuItem Header="MenuItem1" HorizontalAlignment="Left" Width="517">
<MenuItem.Items>
<MenuItem Header="submenuItem1"/>
<MenuItem Header="submenuItem2"/>
</MenuItem.Items>
</MenuItem>
<MenuItem Header="MenuItem2"/>
<MenuItem Header="MenuItem3"/>
</StackPanel>
</xctk:SplitButton.DropDownContent>
</xctk:SplitButton>
</Grid>
Problem here is that the sub menu items don't show up. They don't even have the little arrows next to them. You can do this without the SplitButton, just leaving the stackpanel and everything in it, you'll have the same problem. I've tried putting the parent Menu item in its own tag, but I want the sub-menu items to appear to the right of their parent (just like the firefox example: Assuming your firefox window is not maximized, and you've allowed enough screen-space for the item to appear).
the way you're using the MenuItem control is wrong, it is meant to be hosted inside the Menu control or another MenuItem.
As for the solution to your problem, there are two. the first one is to write a custom control that reuses the ContextMenu to host the menu items, you will write something like this:
<m:SplitButton Content="Split Button" Placement="Bottom">
<MenuItem Header="MenuItem 1"/>
<MenuItem Header="MenuItem 2">
<MenuItem Header="MenuItem 1"/>
<MenuItem Header="MenuItem 2"/>
</MenuItem>
</m:SplitButton
http://www.codeproject.com/Articles/20612/A-WPF-SplitButton
the second approach is to host the Menu control inside the DropDownContent and re-style everything, there will be a lot of xaml markup.
the Menu control will be easy to re-style, the only thing you need to do is make sure that menu items are displayed vertically instead of horizontally, using the following markup:
<Style TargetType="Menu">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" IsItemsHost="True" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
the hardest part is styling the MenuItems, they are styled based on their Role property. It can have four possible values:
TopLevelHeader : direct child of Menu with sub-menu items.
TopLevelItem : direct child of Menu without sub-menu items.
SubmenuHeader : direct child of MenuItem with sub-menu items.
SubmenuItem : direct child of MenuItem without sub-menu items.
Regards

Defining another level of menu items within a MenuItem ItemTemplate

I have a list of objects on my WPF window, all having a context menu which allows the user to copy or move items into different panels (so the ItemsSource of the Context menu is this list of panels, and "Copy" and "Move" are sub-menuitems). However, I have a "CanCopy" property defined in the object that determines whether or not the object can actually be copied. How can I show/hide this MenuItem depending on the value of this property? My problem seems to be in defining this variable additional level of MenuItems.
At first I tried something like this, but obviously it's not quite what I'm looking for, since this doubles up the PanelName MenuItem in to two MenuItem containers:
<MenuItem Header="Panels..." ItemsSource="{Binding PanelsList}">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding PanelName}">
<MenuItem Header="Copy" Visibility="{Binding CanCopy,Converter={StaticResource BoolToHiddenConverter}}"/>
<MenuItem Header="Move"/>
</MenuItem>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
Suggestions?
Add as Content not ItemTemplate
<MenuItem Header="Panels..." ItemsSource="{Binding PanelsList}">
<MenuItem Header="{Binding PanelName}">
<MenuItem Header="Copy" Visibility="{Binding CanCopy,Converter={StaticResource BoolToHiddenConverter}}"/>
<MenuItem Header="Move"/>
</MenuItem>
</MenuItem>

Dynamically binding to ViewModel commands on Window's MenuItem

Working on a WPF application using the MVVM structure.
My Window displays a menu and the current ViewModel. On one of the Menu's MenuItems, I want to list some Commands found in the current ViewModel. The commands listed in the Menu will change depending on the ViewModel.
I got this to work just fine, but the style is messed up - the Command MenuItems are inside another menu box or something. I'll attach a screenshot.
I wrapped the ViewModel's ICommand objects (RelayCommands, in this instance) in CommandViewModel, which expose the Command and the Display string I want on the menu. These CommandViewModels are in a list: CurrentWorkspace.AdditionalOptionsCommands.
Here is the XAML for the Menu. Like I said, it works, it shows the right items and the commands are executed. The display is just incorrect - can anybody tell me why and how to fix it? See the screenshot.
<Menu>
<MenuItem Header="_Additional Options..." ItemsSource="{Binding Path=CurrentWorkspace.AdditionalOptionsCommands}">
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type vm:CommandViewModel}">
<MenuItem Header="{Binding Path=DisplayText}" Command="{Binding Path=Command}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
<MenuItem Header="_Testing">
<MenuItem Header="This looks right" />
<MenuItem Header="This looks right" />
</MenuItem>
</Menu>
Current Appearance:
Desired Appearance:
This is because when you specify menu items via ItemsSource each item gets automatically wrapped into a MenuItem object. This way the content defined in the DataTemplate (MenuItem element) gets wrapped into one more MenuItem.
What you need to do instead of defining a DataTemplate is to define a style for the MenuItem where you setup bindings to the view model's properties and use this style as ItemContainerStyle on the parent MenuItem:
<Window.Resources>
<Style x:Key="CommandMenuItemStyle"
TargetType="{x:Type MenuItem}">
<Setter Property="Header"
Value="{Binding Path=DisplayText}"/>
<Setter Property="Command"
Value="{Binding Path=Command}"/>
</Style>
</Window.Resources>
...
<Menu>
<MenuItem Header="_Additional Options..."
ItemsSource="{Binding Path=CurrentWorkspace.AdditionalOptionsCommands}"
ItemContainerStyle="{StaticResource CommandMenuItemStyle}"/>
<MenuItem Header="_Testing">
<MenuItem Header="This looks right" />
<MenuItem Header="This looks right" />
</MenuItem>
</Menu>
See http://drwpf.com/blog/2008/03/25/itemscontrol-i-is-for-item-container/ for an in-depth explanation on how item containers work with ItemsControl controls.

Resources