none
Gesture of Command within UserControl is not working?

    Question

  • I have a WPF Window, and UserControl inside this window. In each of the control I have a menu and several buttons to be associated with commands.

    Here is my Xaml of my main window:
    1 <Window x:Class="CommandTest.Window1" 
    2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    4     xmlns:UserControl="clr-namespace:CommandTest" 
    5     Title="Window1" Height="300" Width="300">  
    6     <Window.CommandBindings> 
    7         <CommandBinding x:Name="SaveCommand" Command="ApplicationCommands.Save" Executed="SaveCommand_Executed" CanExecute="SaveCommand_CanExecute"/>  
    8         <CommandBinding x:Name="HelpCommand" Command="ApplicationCommands.Help" Executed="HelpCommand_Executed" CanExecute="HelpCommand_CanExecute"/>  
    9     </Window.CommandBindings> 
    10  
    11     <StackPanel> 
    12         <Menu> 
    13             <MenuItem Header="File">  
    14                 <MenuItem Header="Save" Command="ApplicationCommands.Save"></MenuItem> 
    15                 <MenuItem Header="Help" Command="ApplicationCommands.Help"></MenuItem> 
    16             </MenuItem> 
    17         </Menu> 
    18         <Button Command="ApplicationCommands.Save" CommandParameter="Save Me">Save</Button> 
    19         <Button Command="ApplicationCommands.Help" CommandParameter="Help Me">Help</Button> 
    20         <UserControl:NestedControl></UserControl:NestedControl> 
    21     </StackPanel> 
    22 </Window> 

    In line 4 above I referenced my UserControl to be used in line 20.

    The C# code of main window is
    1 using System.Windows;  
    2 using System.Windows.Input;  
    3  
    4 namespace CommandTest {  
    5     public partial class Window1 : Window {  
    6         public Window1() {  
    7             InitializeComponent();  
    8         }  
    9  
    10         private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e) {  
    11             System.Windows.MessageBox.Show("Save""Save");  
    12         }  
    13  
    14         private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {  
    15             e.CanExecute = true;  
    16         }  
    17  
    18         private void HelpCommand_Executed(object sender, ExecutedRoutedEventArgs e) {  
    19             System.Windows.MessageBox.Show("Help""Help");  
    20         }  
    21  
    22         private void HelpCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {  
    23             e.CanExecute = true;  
    24         }  
    25     }  
    26
    It is very simple, whenever a command executed, program displays a message box.

    My Xaml for my UserControl is
    1 <UserControl x:Class="CommandTest.NestedControl" 
    2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
    4     <UserControl.CommandBindings> 
    5         <CommandBinding x:Name="NewCommand" Command="ApplicationCommands.New" CanExecute="NewCommand_CanExecute" Executed="NewCommand_Executed"/>  
    6         <CommandBinding x:Name="OpenCommand" Command="ApplicationCommands.Open" CanExecute="OpenCommand_CanExecute" Executed="OpenCommand_Executed"/>  
    7     </UserControl.CommandBindings> 
    8     <StackPanel> 
    9         <Menu> 
    10             <MenuItem Header="Project">  
    11                 <MenuItem Header="New" Command="ApplicationCommands.New"></MenuItem> 
    12                 <MenuItem Header="Open" Command="ApplicationCommands.Open"></MenuItem> 
    13             </MenuItem> 
    14         </Menu> 
    15         <Button Command="ApplicationCommands.New">New</Button> 
    16         <Button Command="ApplicationCommands.Open">Open</Button> 
    17     </StackPanel> 
    18 </UserControl> 

    and C# code for the UserControl is
    1 using System.Windows.Controls;  
    2 using System.Windows.Input;  
    3  
    4 namespace CommandTest {  
    5     public partial class NestedControl : UserControl {  
    6         public NestedControl() {  
    7             InitializeComponent();  
    8         }  
    9  
    10         private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {  
    11             e.CanExecute = true;  
    12         }  
    13  
    14         private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e) {  
    15             System.Windows.MessageBox.Show("New""New");  
    16         }  
    17  
    18         private void OpenCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) {  
    19             e.CanExecute = true;  
    20         }  
    21  
    22         private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e) {  
    23             System.Windows.MessageBox.Show("Open""Open");  
    24         }  
    25     }  
    26
    Basically it does the same job as main window.

    When I run the application I can see 2 sets of menu/buttons. The set on top is defined in my main window, and lower one is from my UserControl.

    If I press "Ctrl-S" and "F1" (commands defined in main window) I can see both message box, no problem. But if I press "Ctrl-N' and "Ctrl-O" (commands defined in UserControl) nothing actually executes, even though I can see all short-cut definition beside menu item name.

    Can anybody tell me why this happens? How can I make gesture inside UserControl work?

    Thanks
    Hardy
    Wednesday, February 4, 2009 3:05 AM

Answers

  • Hello Hardy,

      It is due to the KeyBoard focus. 

      If we click tab key to move the keyboard focus to the user control, then press "Ctrl-N' or "Ctrl-O".

      The command will be invoked.
      
      Related links:
     
              Commanding Overview

    Focus Overview

      Thanks.

    Please mark the replies as answers if they help and unmark them if they provide no help
    • Marked as answer by Hua Chen Friday, February 13, 2009 9:53 AM
    Friday, February 6, 2009 3:49 AM
  • Hello Hardy,

       Sorry for the delay.
     
        FocusManager.SetIsFocusScope(this.myUserControl, true) doesn't set the usercontrol with Keyboard Focus.

       In the previous code, when other controls (no UserControl) get KeyBoard Focus, there is no Command Source for the New and Open command. 

        So if we press "Ctrl-N' and "Ctrl-O", the handlers at user control doesn't execute.

        When the user control gets the Keyboard focus, the Command is fired.

       Here is a way we can Key fire to the window.

       Sample code.

       

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Navigation;  
    using System.Windows.Shapes;  
     
    namespace CommandIssueOne  
    {  
        /// <summary>  
        /// Interaction logic for Window1.xaml  
        /// </summary>  
        public partial class Window1 : Window  
        {  
            public Window1()  
            {  
                InitializeComponent();  
     
                KeyGesture keyg = new KeyGesture(Key.N, ModifierKeys.Control);  
     
                KeyBinding kb = new KeyBinding(ApplicationCommands.New,keyg);  
     
                kb.CommandTarget = UCon;  
     
                this.InputBindings.Add(kb);  
     
            }  
            private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)  
            {  
                System.Windows.MessageBox.Show("Save""Save");  
            }  
     
            private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)  
            {  
                e.CanExecute = true;  
            }  
     
            private void HelpCommand_Executed(object sender, ExecutedRoutedEventArgs e)  
            {  
                System.Windows.MessageBox.Show("Help""Help");  
            }  
     
            private void HelpCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)  
            {  
                e.CanExecute = true;  
            }          
        }  

    We add the InputBinding

     KeyGesture keyg = new KeyGesture(Key.N, ModifierKeys.Control);  
     
                KeyBinding kb = new KeyBinding(ApplicationCommands.New,keyg);  
     
                kb.CommandTarget = UCon;  
     
                this.InputBindings.Add(kb); 

    Xaml:

    <Window x:Class="CommandIssueOne.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:CommandIssueOne" 
        Title="Window1" Height="300" Width="344">  
          
        <Window.CommandBindings> 
            
            <CommandBinding x:Name="SaveCommand" Command="ApplicationCommands.Save" Executed="SaveCommand_Executed" CanExecute="SaveCommand_CanExecute"/>  
             
            <CommandBinding x:Name="HelpCommand" Command="ApplicationCommands.Help" Executed="HelpCommand_Executed" CanExecute="HelpCommand_CanExecute"/>  
     
        </Window.CommandBindings> 
         
        <StackPanel> 
             
            <Menu> 
                
                <MenuItem Header="File">  
                    
                    <MenuItem Header="Save" Command="ApplicationCommands.Save"></MenuItem> 
                      
                    <MenuItem Header="Help" Command="ApplicationCommands.Help"></MenuItem> 
     
                </MenuItem> 
                  
            </Menu> 
            
            <Button Command="ApplicationCommands.Save" CommandParameter="Save Me">Save</Button> 
             
            <Button Command="ApplicationCommands.Help" CommandParameter="Help Me">Help</Button> 
            
            <local:NestedControl x:Name="UCon">  
                  
            </local:NestedControl> 
            
        </StackPanel> 
          
    </Window> 

    If you have any question please let me know.

     Thanks.

      
      

      


    Please mark the replies as answers if they help and unmark them if they provide no help
    • Edited by Hua Chen Friday, February 13, 2009 9:47 AM Edit..
    • Marked as answer by Hua Chen Friday, February 13, 2009 9:53 AM
    Friday, February 13, 2009 9:41 AM

All replies

  • Hello Hardy,

      It is due to the KeyBoard focus. 

      If we click tab key to move the keyboard focus to the user control, then press "Ctrl-N' or "Ctrl-O".

      The command will be invoked.
      
      Related links:
     
              Commanding Overview

    Focus Overview

      Thanks.

    Please mark the replies as answers if they help and unmark them if they provide no help
    • Marked as answer by Hua Chen Friday, February 13, 2009 9:53 AM
    Friday, February 6, 2009 3:49 AM
  • Thanks for your input.

    I tried to call FocusManager.SetIsFocusScope(this.myUserControl, true); in my main window to include my entire user control, it still does not seem to make my user control to be focused by default.
    Sunday, February 8, 2009 1:08 AM
  • Hello Hardy,

       Sorry for the delay.
     
        FocusManager.SetIsFocusScope(this.myUserControl, true) doesn't set the usercontrol with Keyboard Focus.

       In the previous code, when other controls (no UserControl) get KeyBoard Focus, there is no Command Source for the New and Open command. 

        So if we press "Ctrl-N' and "Ctrl-O", the handlers at user control doesn't execute.

        When the user control gets the Keyboard focus, the Command is fired.

       Here is a way we can Key fire to the window.

       Sample code.

       

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
    using System.Windows.Documents;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
    using System.Windows.Navigation;  
    using System.Windows.Shapes;  
     
    namespace CommandIssueOne  
    {  
        /// <summary>  
        /// Interaction logic for Window1.xaml  
        /// </summary>  
        public partial class Window1 : Window  
        {  
            public Window1()  
            {  
                InitializeComponent();  
     
                KeyGesture keyg = new KeyGesture(Key.N, ModifierKeys.Control);  
     
                KeyBinding kb = new KeyBinding(ApplicationCommands.New,keyg);  
     
                kb.CommandTarget = UCon;  
     
                this.InputBindings.Add(kb);  
     
            }  
            private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)  
            {  
                System.Windows.MessageBox.Show("Save""Save");  
            }  
     
            private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)  
            {  
                e.CanExecute = true;  
            }  
     
            private void HelpCommand_Executed(object sender, ExecutedRoutedEventArgs e)  
            {  
                System.Windows.MessageBox.Show("Help""Help");  
            }  
     
            private void HelpCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)  
            {  
                e.CanExecute = true;  
            }          
        }  

    We add the InputBinding

     KeyGesture keyg = new KeyGesture(Key.N, ModifierKeys.Control);  
     
                KeyBinding kb = new KeyBinding(ApplicationCommands.New,keyg);  
     
                kb.CommandTarget = UCon;  
     
                this.InputBindings.Add(kb); 

    Xaml:

    <Window x:Class="CommandIssueOne.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:CommandIssueOne" 
        Title="Window1" Height="300" Width="344">  
          
        <Window.CommandBindings> 
            
            <CommandBinding x:Name="SaveCommand" Command="ApplicationCommands.Save" Executed="SaveCommand_Executed" CanExecute="SaveCommand_CanExecute"/>  
             
            <CommandBinding x:Name="HelpCommand" Command="ApplicationCommands.Help" Executed="HelpCommand_Executed" CanExecute="HelpCommand_CanExecute"/>  
     
        </Window.CommandBindings> 
         
        <StackPanel> 
             
            <Menu> 
                
                <MenuItem Header="File">  
                    
                    <MenuItem Header="Save" Command="ApplicationCommands.Save"></MenuItem> 
                      
                    <MenuItem Header="Help" Command="ApplicationCommands.Help"></MenuItem> 
     
                </MenuItem> 
                  
            </Menu> 
            
            <Button Command="ApplicationCommands.Save" CommandParameter="Save Me">Save</Button> 
             
            <Button Command="ApplicationCommands.Help" CommandParameter="Help Me">Help</Button> 
            
            <local:NestedControl x:Name="UCon">  
                  
            </local:NestedControl> 
            
        </StackPanel> 
          
    </Window> 

    If you have any question please let me know.

     Thanks.

      
      

      


    Please mark the replies as answers if they help and unmark them if they provide no help
    • Edited by Hua Chen Friday, February 13, 2009 9:47 AM Edit..
    • Marked as answer by Hua Chen Friday, February 13, 2009 9:53 AM
    Friday, February 13, 2009 9:41 AM
  • Thanks, your code is very cool and it works for me!

    I may have another question not related to this topic.

    I have a Save As command
    <CommandBinding x:Name="SaveAsCommand" Command="ApplicationCommands.SaveAs" CanExecute="SaveAsCommand_CanExecute" Executed="SaveAsCommand_Executed" /> 

    It binds to a menu item
    <MenuItem Command="ApplicationCommands.SaveAs"></MenuItem> 

    I checked document, default gesture is Ctrl + H. But "Ctrl + H" does not display in menu item (unlike Open / New command, the key gestures are displayed by default). How can I make SaveAs to display key gesture as well?

    Thanks
    Hardy
    Saturday, February 14, 2009 3:12 AM
  • Hello Hardy,

      It seems to be an issue.

      Not sure why.

      A workaround is also add InputBinding manually

     KeyGesture keygHSaveAs = new KeyGesture(Key.H, ModifierKeys.Control);  
     
                KeyBinding kbH = new KeyBinding(ApplicationCommands.SaveAs, keygHSaveAs);  
     
                kbH.CommandTarget = UCon;  
     
                this.InputBindings.Add(kbH); 

    Thanks.

    Please mark the replies as answers if they help and unmark them if they provide no help
    Thursday, February 19, 2009 3:58 AM
  • -deleted-
    Thursday, January 28, 2010 6:07 AM