开发者

Using WPF Commands with Canvas doesn't work

开发者 https://www.devze.com 2023-01-01 01:12 出处:网络
I am having a custom canvas derived from Canvas. It contains few ApplicationCommands like New/Open/Save etc. added like this -

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:

  1. make sure your canvas (or a control on it) has Focusable="True"
  2. 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, or ToolBar 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));
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号