Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
CommandRouting using a button.
Message
From
11/04/2008 15:59:01
 
 
To
11/04/2008 13:09:49
General information
Forum:
ASP.NET
Category:
Windows Presentation Foundation (WPF)
Miscellaneous
Thread ID:
01309791
Message ID:
01310075
Views:
14
This message has been marked as a message which has helped to the initial question of the thread.
>>>Thought I'd post this just in case someone else comes across this problem:
>>>
>>><Button Command="ApplicationCommands.Save">Apply</Button>
>>>
>>>This works as expected if the button is on a toolbar or the command is on a menu item.
>>>But if it's just a button on a form the command binding:
>>>
>>>CommandBinding SaveCmdBinding = new CommandBinding(ApplicationCommands.Save,
>>>                                                   SaveCmdExecuted,
>>>                                                   SaveCmdCanExecute);
>>>CommandBindings.Add(SaveCmdBinding);
>>>
>>>Only appears to walk the visual tree of the button and not the visual tree of the item with focus. Setting Focusable="False" on the button doesn't fix this :(
>>
>>Hi,
>>I tried testing this. AFAICS the button, whether in a toolbar or on the form, gets focus before the commands are handled - i.e. no difference in behaviour.
>>
>>>So the command needs to be bound to a parent of the button.
>>Again it seems to work the same for me whether I add the binding to the button or the form.
>>
>>Or am I misunderstanding your post?
>>Regards,
>>Viv
>
>Here's the demo code I wrote to figure this out:
>
>WPF Project - WpfCommandBinding
>Window1.Xaml
><Window x:Class="WpfCommandBinding.Window1"
>   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>   xmlns:local="clr-namespace:WpfCommandBinding"
>   Title="Window1" Height="300" Width="300">
>   <DockPanel>
>      <Menu DockPanel.Dock="Top" >
>        <MenuItem Header="Save" Command="ApplicationCommands.Save"></MenuItem>
>      </Menu>
>    <ToolBar DockPanel.Dock="Top" Height="25" >
>    <Button DockPanel.Dock="Bottom" Height="25" Command="ApplicationCommands.Save">Save</Button>
>    </ToolBar>
>    <Button DockPanel.Dock="Bottom" Height="25" Command="ApplicationCommands.Save">Save</Button>
>    <local:UserControl1 x:Name="userControl">
>    </local:UserControl1>
>  </DockPanel>
></Window>
>
>
>Window1.Xaml.cs
>using System;
>using System.Diagnostics;
>using System.Windows;
>using System.Windows.Input;
>
>namespace WpfCommandBinding
>  {
>  /// <summary>
>  /// Interaction logic for Window1.xaml
>  /// </summary>
>  public partial class Window1 : Window
>    {
>    public Window1()
>      {
>      InitializeComponent();
>      this.userControl.textBox1.Focus();
>
>      CommandBinding SaveCmdBinding = new CommandBinding(ApplicationCommands.Save,
>                                                         SaveCmdExecuted,
>                                                         SaveCmdCanExecute);
>      // Never Works for the button :(
>      //CommandManager.RegisterClassCommandBinding(typeof(UserControl1), SaveCmdBinding);
>
>      // Never Works for the button :(
>      userControl.CommandBindings.Add(SaveCmdBinding);
>
>      // Works for Everything
>      //this.CommandBindings.Add(SaveCmdBinding);
>
>      // Has no effect.
>      //CommandManager.InvalidateRequerySuggested();
>      }
>
>    public void SaveCmdExecuted(object target, ExecutedRoutedEventArgs e)
>      {
>      String command, targetobj;
>      command = ((RoutedCommand)e.Command).Name;
>      targetobj = ((FrameworkElement)target).Name;
>      MessageBox.Show("The " + command + " command has been invoked on target object " + targetobj);
>      }
>
>    public void SaveCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
>      {
>      Debug.WriteLine("SaveCmdCanExecute "+DateTime.Now.ToString());
>      e.CanExecute = true;
>      }
>    }
>  }
>
>
>UserControl1.Xaml
><UserControl x:Class="WpfCommandBinding.UserControl1"
>    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>    Height="92" Width="216">
>    <Grid>
>    <TextBox Margin="33,32,65,37" Name="textBox1" />
>    <Button Height="23" Margin="33,0,108,6" Name="button1" Click="button1_Click" VerticalAlignment="Bottom">Button</Button>
>  </Grid>
></UserControl>
>
>
>UserControl1.Xaml.cs
>using System.Windows;
>using System.Windows.Controls;
>using System.Windows.Input;
>
>namespace WpfCommandBinding
>  {
>  /// <summary>
>  /// Interaction logic for UserControl1.xaml
>  /// </summary>
>  public partial class UserControl1 : UserControl
>    {
>    public UserControl1()
>      {
>      InitializeComponent();
>      }
>    private void button1_Click(object sender, RoutedEventArgs e)
>      {
>      // No Effect
>      CommandManager.InvalidateRequerySuggested();
>      }
>    }
>  }
>
>
>The MenuItem and ToolBar button are both enabled and work. The two buttons on the window are disabled unless you move the command binding to this.CommandBindings.Add(SaveCmdBinding); then they also work.
>
>BTW I really like the command system it makes it real easy to setup most of your basic toolbar and menu items. Ctrl+S also works in this program with no added code.
>
>The reason I mentioned Focus is that if you don't bind the command directly to a target the default target is supposed to be the item with focus.

When I first tried your code my question was not why the windows level button didn't work - but why the ToolBar/MenuItem buttons *did*
Turns out the Toolbar and Menu have special functionality that automatically sets the CommandTarget to the control with focus. To get the windows button to fire the event in this scenario you need to set its CommandTarget property explicitly:
CommandTarget="{Binding ElementName=userControl}"
BTW this info found in the Apress 'WPF in C#2008' which turned up today - looks good; certainly better coverage on Commands than from WPF Unleashed.
HTH,
Viv
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform