MenuItem.Header and MenuItem.Icon DataTemplate - wpf

I have a menu with the two following menu items:
<MenuItem Header="Item1">
<MenuItem.Icon>
<cc:Icon ImageSource="..." Size="22"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Item2">
<MenuItem.Icon>
<cc:Icon ImageSource="..." Size="22"/>
</MenuItem.Icon>
</MenuItem>
As you can see each Item has a name as the "Header" and an Icon (my own control) as an an "Icon".
Instead of writing them explicitly in the XAML I want to Bind the ItemsSource to a List<MenuItem> object in my ViewModel, like this:
ItemsSource="{Binding Path=SomeMenu}"
My MenuItem class has the fields "String Name" and ImageSource Icon which I want to bind to the Header and the Icon parts of my menu item exactly how I did here.
I thought the right way was to use a DataTemplate, like this:
<Menu.ItemTemplate>
<DataTemplate>
<!-- TODO: Bind the Header and Icon properties-->
<TextBlock Text="{Binding Path=Name}"/>
<!-- how to bind the icon? -->
</DataTemplate>
<Menu.ItemTemplate>
But I don't understand how to define the Header and the Icon templates separately.
How do I accomplish this, than?
update: I want the <cc:Icon> to appear whereever in the menuItem template there is a <contentPresenter Source="Icon"> and the textBox the appear whereever there is a <contentPresenter Source="Header">

i believe this is what you want:
<Menu ItemsSource="{Binding SomeMenu}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon">
<Setter.Value>
<cc:Icon Source="{Binding Icon}"></Image>
</Setter.Value>
</Setter>
<Setter Property="Header" Value="{Binding Name}"/>
</Style>
</Menu.ItemContainerStyle>
</Menu>
or did i fail miserably again? :)

Related

How can I add context menu item to a textBox inside of the FlowDocumentScrollViewer

I have my PDFDocument bound to the FlowDocumentScrollViewer.
<FlowDocumentScrollViewer
Document="{Binding Path=PDFDocument}"
/>
How can I add a new context menu item to a text box inside of the viewing area
Eventually I found how to do it
You can attach the context menu to each of TextBox Elements using a style property setter like this:
<Window.Resources>
<ContextMenu x:Key="contextMenu" >
<MenuItem Name="mnuOpen" Header="_Open Link" Command="{Binding TextBoxContextMenuCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/>
<MenuItem Name="mnuView" Header="_View Properties" Command="{Binding TextBoxContextMenuCommand}"/>
</ContextMenu>
<Style TargetType="TextBox">
<Setter Property="ContextMenu" Value="{DynamicResource contextMenu}" />
</Style>
</Window.Resources>

Xceed extended WPF datagrid select row with right click

I am trying to add a context menu to an Xceed extended WPF datagrid. I am able to show the context menu and the commands fire from the menu, but right clicking on a row does not set it as the selected row and so the wrong record is used by the command.
Is there a way to change the way the selected item is set so that it can be updated by right click?
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource RecordsForList}}" SelectedItem="{Binding SelectedRecord}">
<xcdg:DataGridControl.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding OpenCommand}" Header="Open" />
</ContextMenu>
</xcdg:DataGridControl.ContextMenu>
</xcdg:DataGridControl>
Instead of changing the way selecting an item works, you could pass the current item as a command parameter to the command if you set the ContextMenu property of each individual DataRow:
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource RecordsForList}}" SelectedItem="{Binding SelectedRecord}">
<xcdg:DataGridControl.ItemContainerStyle>
<Style TargetType="xcdg:DataRow">
<Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType=xcdg:DataGridControl}}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Command="{Binding PlacementTarget.Tag.OpenCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}" Header="Open" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</xcdg:DataGridControl.ItemContainerStyle>
</xcdg:DataGridControl>
The other option would be to write some code in the view that actually selects an item on right-click, e.g.:
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource RecordsForList}}" SelectedItem="{Binding SelectedRecord}">
<xcdg:DataGridControl.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding OpenCommand}" Header="Open" />
</ContextMenu>
</xcdg:DataGridControl.ContextMenu>
<xcdg:DataGridControl.ItemContainerStyle>
<Style TargetType="xcdg:DataRow">
<EventSetter Event="PreviewMouseRightButtonDown" Handler="xgrid_PreviewMouseRightButtonDown" />
</Style>
</xcdg:DataGridControl.ItemContainerStyle>
</xcdg:DataGridControl>
private void xgrid_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Xceed.Wpf.DataGrid.DataRow row = sender as Xceed.Wpf.DataGrid.DataRow;
xgrid.CurrentItem = row.DataContext;
}

I want to be able to specify a style for a tooltip on some MenuItems, how do I do that?

I want to specify a template for the tooltips of some MenuItem controls on my views. I've put the following into a resource dictionary:
<Style TargetType="{x:Type ToolTip}" x:Key="MenuItemToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<HeaderedContentControl>
<HeaderedContentControl.Header>
<TextBlock FontSize="20" Background="#2288C6" Foreground="White" Padding="3">Click to report a bug</TextBlock>
</HeaderedContentControl.Header>
<HeaderedContentControl.Content>
<StackPanel>
<TextBlock Margin="0,5">Please do <Run FontWeight="Bold">not</Run> change the send To email address.</TextBlock>
<TextBlock>Also, leave the <Run FontStyle="Italic">BUG: BOTS</Run> in the subject line alone.</TextBlock>
<!-- more text blocks, but removed for brevity -->
</StackPanel>
</HeaderedContentControl.Content>
</HeaderedContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
Then in one of the views I've tried using it like so:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.Style>
<Style Resources="{StaticResource MenuItemToolTip}" />
</MenuItem.Style>
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
At first I tried this, but this was just as bad:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}" ToolTip="{StaticResource MenuItemToolTip}">
<MenuItem.Header>
<Path Data="{StaticResource BugIconData}"
Stretch="Uniform"
Fill="#77000000"
Width="20"
RenderTransformOrigin="0.25,0.25"
Height="20" />
</MenuItem.Header>
So, how do I get my style into a resource dictionary so that I can use it on some MenuItems, but not all?
The problem with your first approach is that Style.Resources accepts a ResourceDictionary but you are setting it to a Style
Your second approach does not work because you are applying a Style object to the ToolTip property. So an implicit ToolTip is created which tries to Render your style. But since Style is not a UIElement,
what you get is a TextBlock with it's Text property set to whatever text is returned from Style.ToString, which is the name of the Style class by default.
The simplest way here would be to explicitly create a ToolTip for each of your MenuItems and set the styles there. For example:
<MenuItem Background="{x:Null}" Foreground="#FF706C6C" Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style={StaticResource MenuItemToolTip} Content="Your Tooltip text" />
</MenuItem.ToolTip>
</MenuItem>
Another option would be to add an implicit style to the Resources property of the MenuItem so that it will be applied
to all ToolTips inside the visual tree of the MenuItem.
<MenuItem ToolTip="Hello">
<MenuItem.Resources>
<Style TargetType="{x:Type ToolTip}">
.. setters
</Style>
</MenuItem.Resources>
</MenuItem>
I prefer the former because it's the simplest.
You can specify the tooltip style directly by using the tooltip control like this:
<MenuItem Background="{x:Null}"
Foreground="#FF706C6C"
Command="{Binding ViewBugReportingCommand}">
<MenuItem.ToolTip>
<ToolTip Style="{StaticResource MenuItemToolTip}" />
</MenuItem.ToolTip>
...
</MenuItem>

MenuItem Header starts with _

I have some contextMenu which shows list of object.
My problem is when one of the objects starts with underline ("_") for example : _obj1,
and the results is that the mentitem displayed without the underline : obj1".
Any idea?
I fix it by changing the header template.
<Style TargetType="{x:Type MenuItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Header, RelativeSource= {RelativeSource Mode=FindAncestor, AncestorType={x:Type MenuItem}}}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I think you may miss a feature provided by wpf when using a underline-start name.
When you use _obj1, you get the menutime displayed as obj1, but you should try press ALT then you will see the obj1 "underlined" and you can use ALT+o (the first character of the obj name) to "press" the menuitem without using a Mouse.
For example, when you write this:
<MenuItem Header="_File">
<MenuItem .../>
</MenuItem>
Then you just see the Menu with "File", but you can use ALT+F as you are clicking this MenuItem.
Just try this and you shall understand.

Sub Menu Item Command MVVM

<MenuItem Header="Flag(s)" ItemsSource="{Binding Path=LineItemFlags}" Command="{Binding AssignFollowupCommand}">
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FlagName}">
</TextBlock>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
For the parent Item i mean menu item i have a command it's invoking i want to know how to setup command for Sub Menu item
Rather than setting the ItemTemplate, set the ItemContainerStyle. Give it a style that sets the Header and Command properties of the menu item.
<MenuItem Header="_Recent Files" ItemsSource="{Binding RecentFiles}">
<MenuItem.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding FileName}"/>
<Setter Property="MenuItem.Command" Value="{Binding Open}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
Full example and description on Code Project.

Resources