我正在编写一个wpf应用程序,我正在尝试添加F1帮助支持。
我发现了very usefull class by Nigel Shaw
我使用Microsoft HTML Help Workshop编写了一个测试帮助chm文件。
我将它们集成到我的应用程序中。 我为我的主窗口设置了HelpTopic,我动态添加到主窗口的自定义控件(CC1),以及我动态添加到CC1的另一个自定义控件(CC2)。
当我在主窗口中按F1时,我会得到正确的帮助,但需要打开。 当我在CC1中按F1时,我得到正确的帮助,但要打开。 当我在CC2中按F1时,我得到了CC1的帮助主题。
我在调用GetHelpTopic函数时添加了一些代码来获取控件堆栈,这就是我得到的东西([0]是捕获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
起初我认为ScrollViewer可能会抓住F1并阻止它更深入。 但是后来我会在[6]处开始筹码。
然后我认为问题可能来自CC1和CC2类之间的区别。 但它们都继承自从UserControl继承的相同基类
UserControl - UserControlXY - AnimatedControl - AnimatedControlValidated - CC1
UserControl - UserControlXY - AnimatedControl - AnimatedControlValidated - AnimatedStructure - CC2
更新1: 我越走越近了。 如果我在CC2中的控件内单击,那么我得到以下堆栈
[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
我得到了CC2的正确帮助主题。 因此,当我点击它时,我猜测这是一个关注CC2的问题。
所以我将以下标签添加到CC2:
Focusable="True"
但是在那种情况下,当我点击CC2背景或不可聚焦的元素(例如标签)时,我仍然会得到以前错误的行为......
接下来我添加了一个MouseLeftButtonDown来手动设置焦点
MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(AnimatedStructure_MouseLeftButtonDown);
事件是这样做的:
private void AnimatedStructure_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.Focus();
}
但即便如此,我仍然得到以前错误的帮助主题......
更新2:
这次我加入了CC2
GotFocus += new System.Windows.RoutedEventHandler(AnimatedStructure_GotFocus);
LostFocus += new System.Windows.RoutedEventHandler(AnimatedStructure_LostFocus);
我还修改了AnimatedStructure_MouseLeftButtonDown以使用像这样的FocusManager:
FocusManager.SetFocusedElement(this.Parent, this);
我在GotFocus和LostFocus中放置了一个断点。 当我在CC2内部单击时,FocusManager从AnimatedStructure_MouseLeftButtonDown正确触发了GotFocus 但是,之后我立刻收到了CC2本身的LostFocus。 我查看了RoutedEventArgs,它真的是CC2本身,它消除了自己的焦点。
所以现在我有点迷失了怎么办...... 因为我不能
答案 0 :(得分:0)
最后在一个simple blog entry
中找到了问题和解决方案感谢您撰写该博客文章的人。
简短回答:WPF焦点机制严重受损。
对于长篇答案,只需阅读博客,因为作者会详细说明我遇到的行为发生的原因。
我将以下课程添加到我的解决方案
static class FocusHelper
{
private delegate void MethodInvoker();
public static void Focus(UIElement element)
{
//Focus in a callback to run on another thread, ensuring the main UI thread is initialized by the
//time focus is set
ThreadPool.QueueUserWorkItem(delegate(Object foo) {
UIElement elem = (UIElement)foo;
elem.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(MethodInvoker)delegate()
{
elem.Focus();
Keyboard.Focus(elem);
});
}, element);
}
}
这在CC2中
MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(AnimatedStructure_MouseLeftButtonDown);
private void AnimatedStructure_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
FocusHelper.Focus(this);
}
这就是诀窍。 现在焦点在CC2上正确设置和维护,我得到了正确的HelpTopic
乌拉!