I have a MenuItem like below
<MenuItem Header="Edit">
<MenuItem Header="Copy Direct Link" Icon="{StaticResource CopyIcon}" Command="{Binding CopyImageCommand}" />
<MenuItem Header="Copy Image Data" Icon="{StaticResource CopyIcon}" Command="{Binding CopyImageDataCommand}" />
<MenuItem Header="Paste" Icon="{StaticResource PasteIcon}" Command="{Binding PasteImageCommand}" />
</MenuItem>
Notice the 1st 2 items use the same icon, I get something like below
I tried removing the 2nd item,
<MenuItem Header="Edit">
<MenuItem Header="Copy Direct Link" InputGestureText="Ctrl+C" Icon="{StaticResource CopyIcon}" Command="{Binding CopyImageCommand}" />
<!--<MenuItem Header="Copy Image Data" InputGestureText="Ctrl+Alt+C" Icon="{StaticResource CopyIcon}" Command="{Binding CopyImageDataCommand}" />-->
<MenuItem Header="Paste" InputGestureText="Ctrl+P" Icon="{StaticResource PasteIcon}" Command="{Binding PasteImageCommand}" />
</MenuItem>
then I got something like
How can I reuse Icons?
See this question
An Image can only have one parent so it will be moved from the first MenuItem to the second. You can add the x:Shared attribute like this
<Window.Resources>
<Image x:Key="CopyIcon" x:Shared="False" Source="..." />
</Window.Resources>
From msdn
x:Shared Attribute
When set to false, modifies WPF
resource-retrieval behavior so that
requests for the attributed resource
create a new instance for each request
instead of sharing the same instance
for all requests.
You're most likely declaring CopyIcon as Image type in your resource, something like this:
<Window.Resources>
<Image x:Key="CopyIcon" Source="yourcopyicon.ico"/>
</Window.Resources>
So, the root cause of the problem is, Image is a visual element, since it derives from FrameworkElement (which is a visual element), and a visual element cannot have more than one parent at the same time. That is why the first MenuItem is not showing the icon, since the second MenuItem reset the parent of CopyIcon, making itself parent of the CopyIcon.
Hope this explanation is helpful to you. Now follow what Meleak has said in his response. :-)
Try the following:
<MenuItem Header=“Paste“ >
<MenuItem.Icon><Image Height=“16“ Width=“16“ Source=“paste.jpg“ /></MenuItem.Icon>
</MenuItem>
Related
I built a menu bar using the menu control in WPF and it had been working but at some point the menu started showing up on the top left of my first monitor regardless of where in the screen I had the window. Even if I move the main window to the second monitor the menu still shows up in the first monitor.
Here is the code for the menu control:
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_New" Command="New" InputGestureText="Ctrl+N"/>
<MenuItem Header="_Open" Command="Open" InputGestureText="Ctrl+O" />
<MenuItem Header="_Close" Command="Close" InputGestureText="Ctrl+W" />
<Separator/>
<MenuItem Header="_Save" Command="Save" InputGestureText="Ctrl+S" />
<MenuItem Header="Save _As" Command="SaveAs" InputGestureText="Ctrl+Shift+S" />
<Separator/>
<MenuItem Header="E_xit" Command="{StaticResource CommandBinding_Exit}" InputGestureText="Ctrl+Q" />
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Add" Command="{StaticResource CommandBinding_Add}" InputGestureText="" />
<MenuItem Header="_Edit" Command="{StaticResource CommandBinding_Edit}" InputGestureText="" />
<MenuItem Header="_Delete" Command="Delete" InputGestureText="" />
<Separator/>
<MenuItem Header="Cut" Command="Cut" InputGestureText="Ctrl+X" />
<MenuItem Header="Copy" Command="Copy" InputGestureText="Ctrl+C" />
<MenuItem Header="Paste" Command="Paste" InputGestureText="Ctrl+V" />
</MenuItem>
<MenuItem Header="_View">
<MenuItem x:Name="miShowStatusBar" Header="Show Status Bar" IsCheckable="True" IsChecked="True" Click="miShowStatusBar_Click"/>
<MenuItem x:Name="miShowFullPath" Header="Show Full Path" IsCheckable="True" IsChecked="True" Click="miShowFullPath_Click"/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About"/>
</MenuItem>
</Menu>
The menu is not referenced any where in the code behind so I can't figure out what might be causing this odd menu placement.
I think the source of the OP's problem is in the search box under the MenuBar. It may come from the Margin or Width settings of the search box.
I faced the same problem and found the sources. Here is the boilerplate code to reproduce the same error. The problem is a combination of 5 parts, as shown in the following XAML. Remove any one of them will solve the OP's issue.
You need to bind the XAML View to a ViewModel with public property Films. If the Films collection has any element in it, it will also cause the issue (Part 5).
<Grid x:Name="MainContent">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid >
<Menu>
<MenuItem Header="Film">
<MenuItem Header="New"/>
</MenuItem>
</Menu>
</Grid>
<Grid Grid.Row="1">
<Grid>
<!--Part 1: Remove HorizontalScrollBarVisibility="Auto"-->
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<!--Part 2: Remove ItemsSource="{Binding Films}"-->
<ItemsControl ItemsSource="{Binding Films}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<!--Part 3: Remove the setter tag-->
<Setter Property="Margin" Value="2" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<!--Part 4: Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=ActualWidth}-->
<ContentPresenter Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=ActualWidth}"/>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
</Grid>
This has nothing to do with WPF. It's a possible corruption of the Handedness setting or driver issues if you have a touch screen monitor, tablet PC or have a tablet attached with a bad driver (such as a Wacom drawing tablet).
Type this into the Run dialog: shell:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}.
Once Tablet PC Settings come up, go to the Other tab and in the Handedness section, check the Left Handed option.
I bet that this has something to do with the Xaml-Designer of your Visual Studio instance. I encounter similar strange things because of leaving the Xaml-Designer open while debugging.
Try to kill the XDesProc.exe process and check if the problem still occurs.
Because ToolbarTray does not support proper ItemsSource binding I'm doing things in code behind. Namely filling the tray. How can I tell which toolbar the contextmenu was opened for (with CommandParameter)?
<UserControl.Resources>
<ContextMenu x:Key="ToolbarContextMenu">
<MenuItem Header="Move to top" Command="{ui:CommandHandler MoveToTop}" />
<MenuItem Header="Move to left" Command="{ui:CommandHandler MoveToLeft}" />
<MenuItem Header="Make float" Command="{ui:CommandHandler MakeFloat}" />
</ContextMenu>
</UserControl.Resources>
<ToolBarTray x:Name="MainToolbarTray" Orientation="{Binding Orientation}" ContextMenu="{StaticResource ToolbarContextMenu}"/>
In example above I use a toolkit where commands in ViewModel are decorated with attribute and in xaml command can be defined like this.
(Not the same as suggested. I don't want to find ToolbarTray, but the Toolbar)
EDIT: I just assigned the ContextMenu to Toolbar in code behind and used PlacementTarget as suggested.
I can see my Icon in Designer View, but when I run the program it disappears. What am i missing?
EDIT: The Icon itself is 25 by 25 pixels
<DockPanel>
<Menu DockPanel.Dock="Top" HorizontalAlignment="Right" Background="Transparent">
<MenuItem Header="Help">
<MenuItem.Icon>
<Image Source="Resources/Help.png" />
</MenuItem.Icon>
<MenuItem Header="About" />
<MenuItem Header="Update TechTools" />
</MenuItem>
</Menu>
</DockPanel>
You need to set properties on your Help.png file. Righ-click on it, select properties. You want Build action to "Content" and Copy to output directory either Copy Always or Copy if Newer.
You can also consider setting it as Resource, which will embedd it in the program itself.
So I'm extremely new to XAML and still learning. I've followed several tutorials on the menu and menuitems but I cannot seem to find a way to add something to a menu and not have it be selectable. I tried adding just a label and it still shows as selectable. I tried setting isenabled to false and it did turn grey, but was still selectable. I tried turning off hittest and that didn't work either. My guess is that this has something to do with setting up a custom style, which I know nothing about. I'm going to head back into the googles and dive into that, but in the mean time I wanted to post here to see if anyone could offer insight as to a good direction to head.
Edit:
Simple example that I tried:
<Menu>
<MenuItem Header="My Menu">
<Label Content="Label1"/> //Selectable even though it's a label. I would Expect a label to not be selectable.
<MenuItem Header="Menu Item 1"/> //Selectable as it should be.
<Separator /> //Not selectable
<MenuItem Header="Menu Item 2"/>
<Label Content="Another Label" IsEnabled="False"/> //Selectable even though it is set to IsEnabled=False.
</MenuItem>
</Menu>
This may work a bit more like what you want. I added Focusable="False" and IsHitTestVisible="False". Note I had to change the last <Label> to <MenuItem> since Focusable="False" didn't quite do it there.
<Menu>
<MenuItem Header="My Menu">
<Label Content="Label1"/>
<MenuItem Header="Menu Item 1" Focusable="False" IsHitTestVisible="False"/>
<Separator />
<MenuItem Header="Menu Item 2"/>
<MenuItem Header="Another Label" IsEnabled="False" Focusable="False" IsHitTestVisible="False"/>
</MenuItem>
</Menu>
Take a look at this article Menu Control Tutorial if you use commands the CanExecute method can grey out the item and make it non-selectable
I'd like to get to know how I can set menu entries visible or hidden for certain user roles in XAML code? Eg I have "_MenuEntryForADMIN" which should only visible for user role "admin" and "_MenuEntryForAllUsers" should be visible to all users - role "user".
Here is my XAML code:
<Grid>
<DockPanel>
<MenuItem Header="_MenuEntryForADMIN">
<MenuItem Header="_Master1" Click="btnMaster1_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Master2" Click="btnMaster2_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_MenuEntryForAllUsers">
<MenuItem Header="_Normal1" Click="btnNormal1_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Normal2" Click="btnNormal2_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</DockPanel>
</Grid>
The CS-Code contains the information whether a user has the role "admin" or "user" like this:
User userObject;
public MainWindow(User userObject)
{
InitializeComponent();
this.userObject = userObject; // this.userObject.Role is "admin" or "user"
}
In WPF, it is important to 'shape' your data into the correct structure before you try to display it. By this, I mean that you should filter the data, your MenuItems, in your view model or code behind before displaying them, rather than trying to filter them in the UI.
So rather than defining them all in XAML, create some custom data type to data bind to the various MenuItem properties that you are interested in. Then create a DataTemplate and bind a collection of these to the MenuItem.ItemsSource property. You can find out how to do that from my answer to the Dynamically hiding menu items question. In short, it looks something like this:
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type MenuItem}">
<MenuItem Command="{Binding Command}" CommandParameter="{Binding CommandParameter}"
Header="{Binding Path=Header}" Visibility="{Binding Visible, Converter={
BooleanToVisibilityConverter}}" ItemsSource="{Binding ChildMenuItems}" />
</DataTemplate>
There are also many examples online of filtering data in collections, so I won't go over all of that here. You can find a short example in the “Hiding” part of List question here on Stack Overflow. Basically, you can use LinQ to select just the admin MenuItems something like this:
ChildMenuItems = new ObservableCollection<YourCustomDataType>(
FullCollection.Where(i = i.Role == "admin").ToList());