I am writing a wpf application and I am trying to add F1 help support to it.
I found this very usefull class by Nigel Shaw
I wrote a test help chm file with the Microsoft HTML Help Workshop.
I integrated them to my application. I set the HelpTopic for my main Window, a custom control (CC1) I add dynamically to the Main Window, and to another custom control (CC2) I add dynamically to CC1.
When I press F1 in the Main window, I get the correct help subject to open. When I press F1 in CC1, I get the correct help subject to open. When I press F1 in CC2, I get the help subject of CC1.
I added some code to get the stack of controls when the GetHelpTopic function is called and this is what I get ([0] being the control that catch the F1):
[0] System.Windows.Controls.ScrollViewer
[1] System.Windows.Controls.Grid
[2] System.Windows.Controls.Grid
[3] System.Windows.Controls.Grid
[4] CC1
[5] System.Windows.Controls.Canvas
[6] System.Windows.Controls.ScrollViewer
[7] System.Windows.Controls.Grid
[8] System.Windows.Controls.Grid
[9] CustomPanel
[10] System.Windows.Controls.TabItem
[11] System.Windows.Controls.TabControl
[12] System.Windows.Controls.Grid
[13] MainWindow
At first I thought that maybe the ScrollViewer catches the F1 and prevents it to go deeper. But then I would have gotten the stack starting at [6] instead.
Then I thought that maybe the problem came from a difference between CC1 and CC2 classes. But they both inherit from the same base class which inherit from UserControl
UserControl - UserControlXY - AnimatedControl - AnimatedControlValidated - CC1
UserControl - UserControlXY - AnimatedControl - AnimatedControlValidated - AnimatedStructure - CC2
Update 1: I am getting closer. If I click inside a control in CC2, then I get the following stack
[0] System.Windows.Controls.TextBox
[1] System.Windows.Controls.Grid
[2] System.Windows.Controls.Grid
[3] CC2
[4] System.Windows.Controls.Canvas
[5] System.Windows.Controls.ScrollViewer
[6] System.Windows.Controls.Grid
[7] System.Windows.Controls.Grid
[8] System.Windows.Controls.Grid
[9] CC1
[10] System.Windows.Controls.Canvas
[11] System.Windows.Controls.ScrollViewer
[12] System.Windows.Controls.Grid
[13] System.Windows.Controls.Grid
[14] CustomPanel
[15] System.Windows.Controls.TabItem
[16] System.Windows.Controls.TabControl
[17] System.Windows.Controls.Grid
[18] MainWindow
And I get the correct help topic for CC2. So I am guessing it's a problem of setting the focus on CC2 when I click on it.
So I added the following tag to CC2:
Focusable="True"
But in that case I still get the previously wrong behavior when I click on CC2 background or elements that not focusable (ex: labels)...
So next I added a MouseLeftButtonDown to set the focus manually
MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(AnimatedStructure_MouseLeftButtonDown);
With the event doing this:
private void AnimatedStructure_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.Focus();
}
But even with this I am still getting the previously wrong help topic...
Update 2:
This time I added to CC2
GotFocus += new System.Windows.RoutedEventHandler(AnimatedStructure_GotFocus);
LostFocus += new System.Windows.RoutedEventHandler(AnimatedStructure_LostFocus);
I also modified AnimatedStructure_MouseLeftButtonDown to use the FocusManager like this:
FocusManager.SetFocusedElement(this.Parent, this);
I put a breakpoint in GotFocus and LostFocus. When I click inside CC2, GotFocus is fired properly by the FocusManager from AnimatedStructure_MouseLeftButtonDown BUT, immediately after that I receive a LostFocus from CC2 itself. I looked at the RoutedEventArgs and it is really CC2 itself that removes its own focus.
So now I am a bit lost about what to do... Because of that I cannot
Finally found the problem and the solution in one simple blog entry
Thank you who ever you are who wrote that blog entry.
Short answer: WPF Focus mechanism is badly broken.
For the long answer, simply read the blog as the writer gives details on why the behavior I experienced happens.
I addedf the following class to my solution
And this in CC2
That did the trick. Now the focus is properly set and maintained on CC2 and I get the correct HelpTopic
Hurray!