Implementing an "About" menu item in WPF - c#

It seems to be straightforward to get the Version Number e.g.
string ver Assembly.GetExecutingAssembly().GetName().Version.ToString();
And displaying that string in an "About..." menu item should also be. But Google results all seem complex e.g.
https://stackoverflow.com/questions/2849265/how-to-pass-data-when-using-menuitem-itemcontainerstyle
https://stackoverflow.com/questions/21585828/menuitem-passing-selected-item-to-viewmodel-via-relaycommand-ala-mvvm-light-he
There must be a simple way to do this. Something along the lines of
Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Menu>
<MenuItem Header="File">
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
</MenuItem>
<MenuItem Header="About">
<MenuItem Header="Version"/>
</MenuItem>
<Grid>
</Grid>
</Menu>
</Window>
where the last header becomes "Version" + ver.
Or moving into the more complex
How do I dynamically bind and statically add MenuItems?
public partial class MainWindow : Window
{
private ObservableCollection<MyObject> _windows = new ObservableCollection<MyObject>();
public MainWindow()
{
InitializeComponent();
Windows.Add(new MyObject { Title = "Collection Item 1" });
Windows.Add(new MyObject { Title = "Collection Item 2" });
}
public ObservableCollection<MyObject> Windows
{
get { return _windows; }
set { _windows = value; }
}
}
public class MyObject
{
public string Title { get; set; }
}
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="233" Width="143" Name="UI">
<Window.Resources>
<CollectionViewSource Source="{Binding ElementName=UI, Path=Windows}" x:Key="YourMenuItems"/>
</Window.Resources>
<Grid DataContext="{Binding ElementName=UI}">
<Menu Height="24" VerticalAlignment="Top">
<MenuItem Header="_View" >
<MenuItem Header="Windows">
<MenuItem.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource YourMenuItems}}" />
<MenuItem Header="Menu Item 1" />
<MenuItem Header="Menu Item 2" />
<MenuItem Header="Menu Item 3" />
</CompositeCollection>
</MenuItem.ItemsSource>
<MenuItem.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding Title}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</MenuItem>
</Menu>
</Grid>
(which doesn't display "Collection Item 1" etc for me)

Just for the record, here's an MWE which does the very simple thing I wanted.
using System.Collections.ObjectModel;
using System.Reflection;
using System.Windows;
namespace WpfApp2
{
public partial class MainWindow : Window
{
public ObservableCollection<MyMenuItem> _windows = new ObservableCollection<MyMenuItem>();
public MainWindow()
{
InitializeComponent();
string ver = Assembly.GetExecutingAssembly().GetName().Version.ToString();
MyMenuItem versionMenuItem = new MyMenuItem { Title = "Version " + ver };
Windows.Add(versionMenuItem);
}
public ObservableCollection<MyMenuItem> Windows
{
get { return _windows; }
set { _windows = value; }
}
}
public class MyMenuItem
{
public string Title { get; set; }
}
}
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp2"
Title="MainWindow" Height="233" Width="143" Name="UI">
<Window.Resources>
<CollectionViewSource Source="{Binding ElementName=UI, Path=Windows, FallbackValue=versionMenuItem, TargetNullValue=0}" x:Key="MyMenuItems" />
</Window.Resources>
<Grid DataContext="{Binding ElementName=UI}">
<Menu Height="24" VerticalAlignment="Top">
<MenuItem Header="_Version" >
<MenuItem Header="About">
<MenuItem.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource MyMenuItems}}" />
<MenuItem Header="Licensed To" />
</CompositeCollection>
</MenuItem.ItemsSource >
<MenuItem.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding Title}" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</MenuItem>
</Menu>
</Grid>
</Window>
<Application x:Class="WpfApp2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="MenuItem">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
</Application.Resources>
</Application>
Setting the FallbackValue to versionMenuItem to eliminate one of the Data issues.
<CollectionViewSource Source="{Binding ElementName=UI, Path=Windows, FallbackValue=versionMenuItem, TargetNullValue=0}" x:Key="MyMenuItems" />

Related

What is the proper way of creating side view with a side bar in WPF with MVVMCross?

I studied MVVMCross navigation examples and created ShellView, 1st child view and 2nd child view. Navigation works fine, When I push button in menu I see child view, but when I close ShellView window, MainWindow appears. If I show ShellView in not modal way, both windows appear when I start application, image. How can I fix this problem or there is better way to do it? I also would be happy if someone provide me with documentation about advanced navigation(side bar menu, tabbars, multiple views) or IMvxOverridePresentationAttribute.
ShellView
<views:MvxWindow
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
x:Class="FinanceApp.WpfCore.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<views:MvxWindow.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Mode="PrimaryMid">
<StackPanel Orientation="Horizontal" Margin="10,15">
<ToggleButton x:Name="HamburgerButton" Style="{StaticResource MaterialDesignHamburgerToggleButton}"/>
</StackPanel>
</materialDesign:ColorZone>
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding ElementName=HamburgerButton, Path=IsChecked}" Grid.Row="1">
<materialDesign:DrawerHost.LeftDrawerContent>
<StackPanel Width="250" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
<StackPanel.Resources>
<Style TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="Height" Value="48"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</StackPanel.Resources>
<Button Content="First Child" Command="{Binding NavigateFirstChildCommand}"/>
<Button Content="Second Child" Command="{Binding NavigateSecondChildCommand}" Cursor="Hand"/>
</StackPanel>
</materialDesign:DrawerHost.LeftDrawerContent>
</materialDesign:DrawerHost>
<ContentPresenter Grid.Row="1" Content="{Binding }"/>
</Grid>
</DataTemplate>
</views:MvxWindow.ContentTemplate>
</views:MvxWindow>
ShellView.cs
[MvxContentPresentation]
[MvxViewFor(typeof(ShellViewModel))]
public partial class ShellView : IMvxOverridePresentationAttribute
{
public ShellView()
{
InitializeComponent();
}
public MvxBasePresentationAttribute PresentationAttribute(MvxViewModelRequest request)
{
var instanceRequest = request as MvxViewModelInstanceRequest;
var viewModel = instanceRequest?.ViewModelInstance as ShellViewModel;
return new MvxWindowPresentationAttribute
{
Identifier = $"{nameof(ShellView)}.{viewModel}",
Modal = true
};
}
}
ChildView.xaml
<views:MvxWpfView
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
x:Class="FinanceApp.WpfCore.Views.FirstChildView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="First child view model"/>
</Grid>
</views:MvxWpfView>
ChildView.cs
[MvxContentPresentation]
public partial class FirstChildView : IMvxOverridePresentationAttribute
{
public FirstChildView()
{
InitializeComponent();
}
public MvxBasePresentationAttribute PresentationAttribute(MvxViewModelRequest request)
{
var instanceRequest = request as MvxViewModelInstanceRequest;
var viewModel = instanceRequest?.ViewModelInstance as FirstChildView;
return new MvxContentPresentationAttribute
{
WindowIdentifier = $"{nameof(ShellView)}.{viewModel}",
StackNavigation = true
};
}
}
App.xaml
<views:MvxApplication
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
x:Class="FinanceApp.WpfCore.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FinanceApp.WpfCore"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</views:MvxApplication>

MenuItem template change based on bound data

Basically I have a View which is bound to a ViewModel which has MenuItems.
What I want to do is that whenever the menu title is "-" I want to place a separator.
Theoretically it seems that I can avoid TemplateSelectors but if you think that it's inevitable please share even those solutions.
Here is the XAML:
<Window x:Class="WpfApp1.MenuItemStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MenuItemStyle" Height="300" Width="300">
<DockPanel>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}">
<Menu.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding Title}" Value="-">
<Setter Property="ContentTemplate">
<Setter.Value>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<Separator />
</HierarchicalDataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
<TextBlock Text="{Binding Title}" Background="Red" />
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
<Grid>
</Grid>
</DockPanel>
</Window>
And here is the code behind:
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MenuItemStyle.xaml
/// </summary>
public partial class MenuItemStyle : Window
{
public MenuItemStyle()
{
InitializeComponent();
this.DataContext = this;
}
public ObservableCollection<MenuItem> MenuItems { get; set; } = new ObservableCollection<MenuItem> {
new MenuItem{ Title = "M1"
,Children= new ObservableCollection<MenuItem>{
new MenuItem{ Title = "M2"},
new MenuItem{ Title = "-"},
new MenuItem{ Title = "M3"},
}
}
};
}
public class MenuItem
{
public string Title { get; set; }
public ObservableCollection<MenuItem> Children { get; set; }
}
}
I have searched everywhere for a solution but couldn't find a pragmatic one.
You can create a Style for the MenuItems. Make it either local for a concrete menu instance (by placing in the menu's Resources) or place it in your resource dictionary:
<Menu ItemsSource="{Binding MenuItems}">
<Menu.Resources>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Title}" Value="-">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Separator/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Menu.Resources>
<Menu.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Title}" Background="Red" />
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>

Create MenuItems from Collection

i tried to create MenuItems of collection items - and failed. In detail: I have a simple class ClassA that defines a string-property 'HeadText'.
In my MainViewModel i defined an ObservableCollection property. The collection is filled with 3 items. Now in XAML i want to create MenuItems of these 3 items of type ClassA. I did the following:
<Window.Resources>
<CompositeCollection x:Key="CollA">
<ItemsControl ItemsSource="{Binding Path=MItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding HeadText}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</CompositeCollection>
</Window.Resources>
<Grid>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding Source={StaticResource CollA}}"/>
</Grid>
But all i get is an empty menu bar. Any ideas how i can do this?
The viewmodel and the class ClassA:
public class MainVM
{
public MainVM() {
_mItems.Add(new ClassA() { HeadText = "A" });
_mItems.Add(new ClassA() { HeadText = "B" });
_mItems.Add(new ClassA() { HeadText = "C" });
}
private ObservableCollection<ClassA> _mItems = new ObservableCollection<ClassA>();
public ObservableCollection<ClassA> MItems{
get { return _mItems; }
}
}
public class ClassA
{
public ClassA() { }
public String HeadText { get; set; }
}
Thanks in advance.
Edit:
If i write this, it works:
<Menu DockPanel.Dock="Top" ItemsSource="{Binding MItems}">
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Header" Value="{Binding HeadText}"/>
</Style>
</Menu.ItemContainerStyle>
</Menu>
But i want to do it the other way. And i'm interested why the other way does not work.
I found the answer here. My XAML first looked like this:
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<Window.Resources>
<CollectionViewSource Source="{Binding Path=MItems}" x:Key="source"/>
</Window.Resources>
<StackPanel>
<Menu DockPanel.Dock="Top">
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding HeadText}"/>
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemsSource>
<CompositeCollection>
<MenuItem Header="Static 1"/>
<MenuItem Header="Static 2"/>
<CollectionContainer Collection="{Binding Source={StaticResource source}}"/>
<MenuItem Header="Static 3"/>
</CompositeCollection>
</Menu.ItemsSource>
</Menu>
</StackPanel>
And the MainVM.cs and ClassA:
public class MainVM
{
public MainVM() {
_mItems.Add(new ClassA() { HeadText = "Dyn1" });
_mItems.Add(new ClassA() { HeadText = "Dyn2" });
_mItems.Add(new ClassA() { HeadText = "Dyn3" });
}
private ObservableCollection<ClassA> _mItems = new ObservableCollection<ClassA>();
public ObservableCollection<ClassA> MItems{
get { return _mItems; }
}
}
public class ClassA
{
public ClassA() { }
private string _text = "";
public String HeadText {
get { return _text; }
set { _text = value; }
}
}
This works fine but you have to notice that Visual Studio will give you BindingExpression errors in the case you really mix static and dynamic menu items.
The reason for this is that the XAML parser applies the specified ItemContainerStyle to the dynamic AND to the static menu items: it creates a new MenuItem and binds the HeadText property to the Header property of the newly created MenuItem. This is done for the dynamic menu items as well as for the static ones. Because there is no HeadText property in the MenuItem class, an error is displayed.
The application will not crash, but it's not a good solution. A workaround for this is to split the MenuBar like this:
<StackPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Menu Grid.Column="0">
<MenuItem Header="Static 1"/>
<MenuItem Header="Static 2"/>
</Menu>
<Menu Grid.Column="1">
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding HeadText}"/>
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource source}}"/>
</CompositeCollection>
</Menu.ItemsSource>
</Menu>
<Menu Grid.Column="2">
<MenuItem Header="Static 3"/>
</Menu>
</Grid>
</StackPanel>
Maybe there is a nicer solution. Let me know if this is so.

TreeView's contextmenu appears on the topnode instead of TreeViewItem's

I've got a problem I couldn't find solution for. Here is my TreeView's XAML:
<TreeView ItemsSource="{Binding Parents}" ContextMenu="{StaticResource TreeViewContextMenu}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
And I've also got this style in my ContentControl.Resources:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="ContextMenu" Value="{StaticResource TreeViewItemContextMenu}" />
</Style>
When I rightclick any item apart from the very first one, the TreeViewItemContextMenu appears, just as intended.
But the issue is when I rightclick the topnode, the TreeViewContextMenu appears instead.
I tried to do without the TreeViewContextMenu at all, but then the topnode had no ContextMenu either.
I would be very glad to know, what and where I missed. Thanks in advance.
I'm trying using your xaml code. This is works.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ContextMenu x:Key="TreeViewItemContextMenu">
<MenuItem Header="Item Menu"/>
</ContextMenu>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem Header="Tree Menu"/>
</ContextMenu>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="ContextMenu" Value="{StaticResource TreeViewItemContextMenu}" />
</Style>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Parents}" ContextMenu="{StaticResource TreeViewContextMenu}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
In code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Parents = new ObservableCollection<MyTreeItem>();
var children=new ObservableCollection<MyTreeItem>();
children.Add(new MyTreeItem(){ Name="child1"});
children.Add(new MyTreeItem(){ Name="child2"});
Parents.Add(new MyTreeItem() { Name = "Parent Node", Children = children });
this.DataContext = this;
}
public ObservableCollection<MyTreeItem> Parents { get; set; }
}
public class MyTreeItem {
public string Name { get; set; }
public ObservableCollection<MyTreeItem> Children { get; set; }
}
When i click on the top node and child node, Context menu is same

Scope of menu shortcut key

When I click menu strip and then press shortcut key it works but it does not work otherwise. Is there something to set scope of shortcut key?
XAML:
<Window x:Class="NewGUI_WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:Common;assembly=RecentFileListLib"
Title="Sezor" Height="Auto" Width="Auto" WindowStartupLocation="Manual" Icon="/NewGUI_WPF;component/Images/i161.ICO" WindowStyle="SingleBorderWindow" Focusable="False" ResizeMode="CanResize" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="243" d:DesignWidth="314" SizeToContent="Manual" WindowState="Maximized">
<Window.CommandBindings>
<CommandBinding Command="Save" Executed="SaveCommand" />
<CommandBinding Command="Open" Executed="OpenCommand" />
</Window.CommandBindings>
<Grid>
<Menu Height="23" Name="main_menu" VerticalAlignment="Top" HorizontalAlignment="Stretch" IsMainMenu="True">
<MenuItem Name="MI_Case" Header="Case">
<MenuItem Header="Open" Command="Open">
<MenuItem.Icon>
<Image Height="16" Width="16" Source="/NewGUI_WPF;component/Images/openHS.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save" Name="MainMenu_File_Save" Command="Save">
<MenuItem.Icon>
<Image Height="16" Width="16" Source="/NewGUI_WPF;component/Images/saveHS.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Save as" Name="MainMenu_File_SaveAs" Click="MainMenu_File_SaveAs_Click" />
<common:RecentFileList x:Name="RecentFileList" />
<MenuItem Header="Quit" Click="MainMenu_File_Quit_Click" />
</MenuItem>
<MenuItem Header="View">
<MenuItem Header="Input File" Click="MainMenu_View_InputFile_Click" />
<MenuItem Header="Mesh File" Click="MainMenu_View_meshFile_Click" />
<MenuItem Name="MainMenu_View_Summary" Header="Summary" Click="MainMenu_View_summary_Click" />
</MenuItem>
<MenuItem Header="Define" >
<MenuItem Header="Input File" Click="MainMenu_Define_InputFile_Click" Name="MainMenu_Define_InputFile" />
<MenuItem Header="Mesh File" Click="MainMenu_Define_MeshFile_Click" Name="MainMenu_Define_MeshFile" />
<MenuItem Header="Simulation File" Click="MainMenu_Define_SimulFile_Click" Name="MainMenu_Define_SimulFile" />
<MenuItem Header="Boundaries" Click="MainMenu_Define_BC_Click" />
<MenuItem Header="Initials" Click="MainMenu_Define_Initials_Click" />
<MenuItem Header="Spatial Discretization" Click="MainMenu_Define_SpatDis_Click" />
<MenuItem Header="Flow" Click="MainMenu_Define_Flow_Click" />
<MenuItem Header="Material" Click="MainMenu_Define_Material" />
<MenuItem Header="Algoritm" Click="MainMenu_Define_Algoritm" />
<MenuItem Header="Gradient Reconstruction">
<RadioButton Content="Least-Squares" Checked="Least_Squares_Checked" Name="rad_GR_LS" />
<RadioButton Content="Green-Gauss" Click="Green_Gauss_Checked" Name="rad_GR_GG" />
</MenuItem>
</MenuItem>
<MenuItem Header="Run" >
<MenuItem Header="Simulation" Click="MainMenu_Run_Simulation_Click" />
</MenuItem>
</Menu>
<Frame Height="Auto" HorizontalAlignment="Left" Margin="40,60,30,20" Name="frm_summary" VerticalAlignment="Top" Width="Auto" NavigationUIVisibility="Hidden" />
<StatusBar Height="23" Name="statusBar1" VerticalAlignment="Bottom" Margin="0">
<TextBlock Name="statBar_text_1"></TextBlock>
</StatusBar>
</Grid>
Code:
private void OpenCommand(object sender, ExecutedRoutedEventArgs e) {...}
private void SaveCommand(object sender, ExecutedRoutedEventArgs e) {...}
Remove Focusable="False" in your Window tag.
Looks like you need to add CanExecute to the CommandBinding and a corresponding code behind method.
Here's a minimal demonstration that wires up Control-S to launch the Help command.
The XAML:
<Window x:Class="stackoverflow___scope_of_menu_shortcut_key.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Help" CanExecute="HelpCanExecute" Executed="HelpExecuted"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Help" Key="S" Modifiers="Control"/>
</Window.InputBindings>
<Menu>
<MenuItem Header="File">
<MenuItem Header="Help" Name="HelpMenu" Command="Help"/>
</MenuItem>
</Menu>
</Window>
The code behind:
using System.Windows;
using System.Windows.Input;
namespace stackoverflow___scope_of_menu_shortcut_key
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void HelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
System.Diagnostics.Process.Start("http://www.microsoft.com");
}
}
}
Notice that if you comment out the line:
e.CanExecute = true;
the key bindings no longer function.
Here's your example, stripped down to a bare minimum. This works on my system:
XAML:
<Window x:Class="stackoverflow___scope_of_menu_shortcut_key.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Save" Executed="MyCommand" />
</Window.CommandBindings>
<MenuItem Header="Save" Command="ApplicationCommands.Save"/>
</Window>
Code behind:
using System.Windows;
using System.Windows.Input;
namespace stackoverflow___scope_of_menu_shortcut_key
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MyCommand(object sender, ExecutedRoutedEventArgs e)
{
System.Diagnostics.Process.Start("http://www.microsoft.com");
}
}
}

Categories

Resources