You'll want to investigate ICommand, RoutedUICommand, InputGestureCollection, and CommandManager. It a little more upfront infrastructure work, but the WPF Command pattern allows you to share a command across main menu, context menu's, button clicks, etc. With your actions written as Commands, all the places in your application that use the Command will enable/disable consistently and it add one more layer of indirection to reduce code repetition.
The following example is in VB.Net (sorry, but hopefully it should be easy to translate).
Implement each of your required actions as a class that implements ICommand:
Public Class OpenWindowCommand
Implements ICommand
Public Function CanExecute(parameter as Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
'enter code that determines whether this command should be enabled or not
'if you are listening to some backend logic that changes this state, you can
'raise a CanExecuteChanged event
End Function
Public Sub Execute(parameter as Object) Implements System.Windows.Input.ICommand.Execute
'code that you want to run for the action
End Sub
End Class
Create a class that stores shared instances of each of your Commands.
Public Class MyCommands
Private Shared ReadyOnly openWindowCmd As ICommand = New OpenWindowCommand()
Private Shared _openWindow as RoutedUICommand
Shared Sub New()
'static constructor
Dim shortcut = New KeyGesture(Key.W, ModifierKeys.Control)
RegisterCommand(_openWindow, "OpenWindow", "Open...", shortcut, AddressOf ExecuteOpenWindow, AddressOf CanExecuteOpenWindow)
'add more commands as needed
End Sub
Private Shared Sub RegisterCommand(ByRef command as RoutedUICommand, ByVal name as String, ByVal text as String, ByVal gesture as KeyGesture, ByVal executeHandler as ExecutedRoutedEventHandler, ByVal canExecuteHandler as CanExecuteRoutedEventHandler)
Dim inputs = New InputGestureCollection()
If gesture IsNot Nothing Then inputs.Add(gesture)
command = New RoutedUICommand(text, name, GetType(MyCommands), inputs)
Dim binding = New CommandBinding(command, executeHandler, canExecuteHandler)
Application.Current.MainWindow.CommandBindings.Add(binding)
CommandManager.RegisterClassCommandBinding(GetType(Window),binding)
End Sub
Public Shared ReadOnly Property OpenWindow() as RoutedUICommand
Get
Return _openWindow
End Get
End Property
Public Shared Sub ExecuteOpenWindow(sender as Object, e as ExecutedRoutedEventArgs)
openCmd.Execute(e.Parameter)
End Sub
Public Shared Sub CanExecuteSave(sender as Object, e as CanExecuteRoutedEventArgs)
e.CanExecute = openCmd.CanExecute(e.Parameter)
e.Handled = True
End Sub
End Class
Now in your XAML for your menu you can bind to this command:
<Window.Resources>
<local:MyCommands x:Key="commands"/>
</Window.Resources>
...
<MenuItem Name="mnuOpenWindow" Command="{Binding Path=OpenWindow}"/>
This is a bit more than the minimal requirement to use Commands, but in a reasonably large application I've found this additional infrastructure pretty useful. Once the Commands are written and registered, binding to them in any XAML document is trivial and by exposing Shared Properties for each action through the MyCommands class you can access the commands purely in code if needed.