It seems that a custom CommandHandler is not called for ApplicationCommands.
What we did:
We bound our ToolBar buttons and main MenuItems for e.g. Cut/Copy/Paste to the corresponding ApplicationCommands. No Problems so far. But now we need a custom CommandHandler implementation.
(taken from your examples) where CusytomHandler inherits from CommandHandler and overrides the methods CanCut, Cut etc.
The CustomHandler is instantiated but the overridden methods are never called.
We cannot bind the button or menu item directly to the CommandHandler.CutCommand etc, because they are application wide controls and we would disable the default behavior for cut/copy/paste in all other framework elements in that case.
It seems to work for me. I tried modifying the Gantt sample, which already has a custom CommandHandler, and adding both ways of defining commands for buttons:
<Button Command="{x:Static go:Commands.IncreaseZoom}" CommandTarget="{Binding ElementName=myDiagram}">Zoom In</Button>
<Button Command="{Binding ElementName=myDiagram, Path=CommandHandler.DecreaseZoomCommand}">Zoom Out</Button>
The declaration of the go:Diagram.CommandHandler is already in that sample. Clicking either button works as you would expect, and if you set a breakpoint in the CommandHandler-derived subclass, it stops there.
I’m wondering what is different between your situation and this sample?
That is the command linkage between our toolbar buttons and the ApplicationCommands.
These commands are handled by the Diagram, but the custom handler is not called. That is the problem we have. You bound buttons directly to the Digram’s CommandHandler (different scenario I think ;-)).
The first button in my previous post did not bind directly to the Diagram.CommandHandler.
So let’s try again.
First I add these overrides to the Gantt sample custom CommandHandler:
public override bool CanCopy() {
return base.CanCopy();
}
public override void Copy() {
base.Copy();
}
Then I add a ToolBar to the sample:
<StackPanel>
<ToolBarTray>
<ToolBar>
<Button Command="ApplicationCommands.Copy">Copy</Button>
</ToolBar>
</ToolBarTray>
<Grid>
. . . the rest of the Gantt sample XAML body, including the go:Diagram with the custom go:Diagram.CommandHandler . . .
</Grid>
</StackPanel>
I set a breakpoint in the overridden Copy() method, select a Node – now the Copy button in the ToolBar is enabled. Click that button – it stops at the breakpoint in my override method.
Could you help me by showing what I need to do to modify the Gantt sample to reproduce the problem that you have?
The problem with what you write there is that you cannot share a single local:CustomHandler amongst multiple go:Diagrams. You will need to assign diagram.CommandHandler = new CustomHandler() when each Diagram is instantiated.
It does not work at all. I made a little demo VS2012 Solution containing three different ‘tests’ were you easily cann switch between the cases by commenting/uncommenting the XAML code. I create a new instance of the command handler in my view model and not in the code beside (we cannot acces the diagram because it is defined in the data template).
Scenario: TabControl with data template -> handler not called, but default handler used
Scenario: TabControl with fixed TabItems -> Error: Handler cannot be shared between different diagram
Scenario: StackPanel containing two diagrams-> Error: Handler cannot be shared between different diagram (remember, new handler instance is created in each view model)
If you cannot make sure each Diagram has its own CustomHandler, you can define:
public class CustomDiagram : Diagram {
public CustomDiagram() {
this.CommandHandler = new CustomHandler();
}
}
and use this CustomDiagram in your XAML instead of a regular Diagram with a setting of go:Diagram.CommandHandler
Each CommandHandler has diagram-specific state in it, so a CommandHandler cannot be shared by two or more Diagrams. Your most recent XAML, quoted above, would cause a single (static) CommandHandler instance to be shared by each Diagram created from the DataTemplate. This is why you would get those errors.
When you put a Diagram in a DataTemplate, WPF does not know about copying the CommandHandler when it applies the template. You’ll note that if you put a breakpoint in your CustomHandler’s constructor, it only breaks there once, because only one instance of your class is created.
So you need to make a copy of your custom CommandHandler in some other manner. I just gave you a trivial way to do so, but there might be others that would be suitable for your purposes.