Using WPF Commands with Canvas doesn't work
I am having a custom canvas derived from Canvas
. It contains few ApplicationCommands
like New
/Open
/Save
etc. added like this -
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, New_Executed,
New_Enabled));
New_Enabled
always returns true.
This control is used in a wpf project having a menu bar; New/Open/Save menu button's are present in this menu bar with their Command
set to respective ApplicationCommand
like this -
<syncfusion:SimpleMenuButton
x:Name="NewMenu"
Icon="Images\New_Large.png"
Label="New"
IsEnabled="True"
Command="{x:Static ApplicationCommands.New}"
syncfusion:Ribbon.开发者_如何学GoKeyTip="N">
</syncfusion:SimpleMenuButton>
Command works correctly when focus is present on Canvas
but as soon as focus shifts to other control, New button gets disabled. I have tried setting CommandTarget
to main window but that too doesn't work.
Why this is happening and how can to make sure that New menu button will always be enabled?
The problem is that once your button and canvas share logical focus scope somewhere above in the hierarchy (most likely it is your window) the commands initiated in some menu never reach your canvas.
If you have just one canvas which you want to receive all your commands, just bind CommandTarget
of your buttons to canvas:
...
Command="New"
CommandTarget="{Binding ElementName=TheCanvas}"
...
Note that ICommand
is marked with TypeConverterAttribute
which converts strings like "New" to ApplicationCommands.New
so you don't have to use x:Static
markup extension.
You can do it in one place with Style
for all buttons on the level your menu/toolbar.
However, if you have multiple canvases and want your command to be directed towards currently focused one, you have to do two things:
- make sure your canvas (or a control on it) has
Focusable="True"
- limit the logical focus scope of your toolbar (or whatever container you use for your buttons) by setting
FocusManager.IsFocusScope="True"
on it. Some containers, like Menu, orToolBar
have that on by default. This way once command routing algorithm reaches the scope it will redirect it to the element currently having the keyboard focus.
@repka - Thanks for your response; I had already tried using canvas name as CommandTarget
but it doesn't work; Buttons gets enabled only when focus is on canvas as soon as i Click on some other control in window they gets disabled. I also tried using IsFocusScope
but same result. Thanks for the command name strings tip.
I had to settle with this workaround, although I am not too happy with this -
public WindowMain()
{
InitializeComponent();
//Add commnad bindings
//Need to do this to keep New/Open/Save/Run buttons always enabled
//ToDo:[AJ] Look for better solution then this
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, this.TheCanvas.New_Executed, this.TheCanvas.New_Enabled));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, this.TheCanvas.Open_Executed, this.TheCanvas.Open_Enabled));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, this.TheCanvas.Save_Executed, this.TheCanvas.Save_Enabled));
this.CommandBindings.Add(new CommandBinding(RTDesignerCanvas.Run, this.TheCanvas.Run_Executed));
}
精彩评论