MenuItem Vertical alignment issue - c#

I am facing an issue with MenuItem that whenever I specify an access key, the header alignment is getting disrupted. Below is a sample image wherein I have specified "_New" for New menu item and bound it to New command. You can observe tha the Text "New" is align at bottom and shortcut key is aligned at top. Also for other menu items I have not specified any access key, so they have no issue.
Here is the XAML
<StackPanel DockPanel.Dock="Top">
<Menu Padding="0,5">
<MenuItem x:Name="MnuTask" Header="Task">
<MenuItem x:Name="MnuNew" Header="_New" Command="New"/>
<MenuItem x:Name="MnuSave" Header="Save" Command="Save"/>
<MenuItem x:Name="MnuDelete" Header="Delete" Command="Delete"/>
<Separator/>
<MenuItem x:Name="MnuRefresh" Header="Reload Data" Command="{x:Static Local:MainWindow.RefreshDataCommand}" />
<MenuItem x:Name="MnuHistory" Header="View Range History" Command="{x:Static Local:MainWindow.RangeHistoryCommand}" />
<Separator/>
<MenuItem x:Name="MnuExit" Header="Exit" Command="Close"/>
</MenuItem>
<MenuItem x:Name="MnuView" Header="View">
<MenuItem x:Name="MnuFind" Header="Find Formula"/>
</MenuItem>
</Menu>
</StackPanel>
Could any body let me know what's going on?

Found it. I had the below TextBlock Style present in Resources section of my window. Commenting those lines resolved the issue. (But now I need to apply TextBlock style explicitly using keys :( )
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="3,6,3,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>

Related

Change style for the default context menu in WPF Application

I have an WPF desktop application and many text boxes that automatically have the default context menu with Copy\Cut\Paste commands.
Is there any way to change style of this menu, for example add icons or change Foreground color?
https://ibb.co/y5LRZnY
You could create a TextBox style with a custom ContextMenu:
<Style TargetType="TextBox">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Foreground="Red">
<MenuItem Icon="..." Command="Cut"/>
<MenuItem Icon="..." Command="Copy"/>
<MenuItem Icon="..." Command="Paste"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
And here is how you would set the Icon property of a MenuItem to an image:
<MenuItem Command="Paste">
<MenuItem.Icon>
<Image Source="pic.png" />
</MenuItem.Icon>
</MenuItem>

How to define WPF ContextMenu with a Separator before the last element, using binding on ItemsSource instead of individual MenuItems

I am trying to create a ContextMenu that defines some filters via Checkable MenuItems, with a Separator separating the last MenuItem from the previous ones.
I know I could define and manage the MenuItems and the Separator in the following way:
<ContextMenu HasDropShadow="False" Placement="Bottom">
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked1}" Header="Filter 1"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked2}" Header="Filter 2"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked3}" Header="Filter 3"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked4}" Header="Filter 4"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked5}" Header="Filter 5"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked6}" Header="Filter 6"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked7}" Header="Filter 7"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked8}" Header="Filter 8"/>
<Separator Styles.Separator="Default"/>
<MenuItem IsCheckable="True" IsChecked="{Binding Path=IsChecked9}" Header="Active"/>
</ContextMenu>
But I would rather try to avoid having 9 IsChecked properties in my ViewModel, on top of having the next dev need to add/remove a MenuItem and its associated property when we need to add/remove a filter.
What I'd rather do, is to use the ItemsSource property of the ContextMenu and define an ItemTemplate for each element of the ItemsSource. Unfortunately, if I do this, I am not sure how I can define the Separator before the last element of the ItemsSource like I could do in the previous code snippet.
Is there a way to achieve what I want to do without defining manually each individual MenuItem and its associated properties in the ViewModel?
Based on the following answer:
How do I dynamically bind and statically add MenuItems?
I found an hybrid approach to what I wanted to achieve, which makes sense in my context: the only MenuItem I need to manually add is the last one, which I need to handle differently anyway in my ViewModel, so I don't mind manually adding that one. All the others are however generated automatically based on my AllFiltersExceptTheLastOne ObservableCollection:
<UserControl.Resources>
<CollectionViewSource x:Key="AllFiltersExceptTheLastOne" Source="{Binding Path=Filters}"/>
</UserControl.Resources>
...
<Button.ContextMenu>
<ContextMenu HasDropShadow="False" Placement="Bottom">
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource AllFiltersExceptTheLastOne}}" />
<Separator Margin="0,5,0,5" Styles.Separator="Default"/>
<MenuItem Padding="2,2,2,2" IsCheckable="true" IsChecked="{Binding Path=Filter.IsChecked}" Header="{Binding Path=Filter.Status}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
<ContextMenu.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Padding" Value="2,2,2,2"/>
<Setter Property="MenuItem.IsCheckable" Value="true"/>
<Setter Property="MenuItem.Header" Value="{Binding Path=Status}"/>
<Setter Property="MenuItem.IsChecked" Value="{Binding Path=IsChecked}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>

My menu showing up at the top left of the screen

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.

Click event on a (Context)MenuItem of a ListBox (XamlParseException)

I have a ListBox and within it multiple ListBoxItem objects. When the user right-clicks on a ListBoxItem a ContextMenu should appear with some MenuItem objects. The problem that I have is that when I put a Click event on the MenuItem objects I get a XamlParseException stating the following:
A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
Additional information: 'Set connectionId threw an exception.' Line number '31' and line >position '34'.
I have to admit that I don't fully understand styles and resources and the other aspects of WPF. When I was designing this I just copied my code from the Internet. The code is as follows:
<ListBox Grid.Column="1" Grid.Row="1" MouseDoubleClick="MainListBox_MouseDoubleClick" Name="mainListBox" SelectionChanged="MainListBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Click="OpenMenuItem_Click" Header="Open"/>
<Separator/>
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<Separator/>
<MenuItem Header="Delete"/>
<MenuItem Header="Rename"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
It works when I remove the Click event but of course the ContextMenu becomes useless.
Assign ContextMenu for ListBoxItem as given below.
<ListBox Grid.Column="1" Grid.Row="1" MouseDoubleClick="MainListBox_MouseDoubleClick" Name="mainListBox" SelectionChanged="MainListBox_SelectionChanged">
<ListBox.Resources>
<ContextMenu x:Key="CMenu">
<MenuItem Click="OpenMenuItem_Click" Header="Open"/>
<Separator/>
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<Separator/>
<MenuItem Header="Delete"/>
<MenuItem Header="Rename"/>
</ContextMenu>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu" Value="{StaticResource CMenu}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem Content="Test1"/>
</ListBox>

Tip / idea how can I get a generic context menu?

I want to develop a generic contextmenu in wpf with mvvm. I would like to display it in each viewModel that have a listview with the style: ItemContainerStyle="{DynamicResource ListViewItemContainerStyle}".
The context menu will have 2 options that will be enabled or not depending on some constraints in each view Model. The enabled or not will be managed by the canexecute of the command.
I have no problem if I put it in each view inside the listview, but I would like to have it only in one place other than in each listview. I have tried to put it in the ListViewItemContainerStyle but it shows an exception "it is not possible to add a System.Windows.Controls.ContextMenu to a System.Object". Here is my code snippet
<Style x:Key="ListViewItemContainerStyle"
TargetType="ListViewItem">
.
.
.
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Command="{Binding Path=Command}"
CommandParameter="AddNew">
<MenuItem.Header>
<TextBlock Text="{x:Static p:TextResources.New}" />
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding Path=Command}"
CommandParameter="Delete">
<MenuItem.Header>
<TextBlock Text="{x:Static p:TextResources.Delete}" />
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
.
.
.
Any idea of how to do this?
Try this:
<ContextMenu x:Shared="False" x:Key="ListViewContextMenu>
<MenuItem Command="{Binding Path=Command}"
CommandParameter="AddNew">
<MenuItem.Header>
<TextBlock Text="{x:Static p:TextResources.New}" />
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding Path=Command}"
CommandParameter="Delete">
<MenuItem.Header>
<TextBlock Text="{x:Static p:TextResources.Delete}" />
</MenuItem.Header>
</MenuItem>
</ContextMenu>
<Style x:Key="ListViewItemContainerStyle"
TargetType="ListViewItem">
<Setter Property="ContextMenu" Value="{StaticResource ListViewContextMenu}"/>

Categories

Resources