关于WPF中给Popup设置焦点的问题

最近在用WPF实现一个浏览器外壳,里面放了个Popup,但在给Popup设置焦点时出了个很诡异的问题,三个人研究了大半天才找到答案。
这里我大致讲一下问题和解决方法,希望能帮助到同样遭遇或将会遭遇此问题的你。

问题背景:
VS2012开发WPF窗口程序
其中:
①主窗口一个,用来摆放前进、后退、刷新、停止、地址栏等工具控件,以下称之为“窗体A”
②WebView页面渲染子窗口一个,以下称“窗体B”
③Popup一个,通过spy++可以发现,Popup其实是个完整独立的窗体,所以以下称“Popup窗体P”
④Popup窗体P中包含一文本输入框,以下称之为“文本框T”

问题描述:
①当焦点在“窗体B”中的可编辑区域时(如“窗体B”中打开的是百度,焦点在百度输入框里),鼠标点击“Popup窗体P”中的“文本框T”,然后尝试输入字符,发现输入的字符跑到“窗体B”中去了(如输入的字符到百度输入框里去了)。
②当焦点在“窗体B”中的非可编辑区域时,鼠标点击“Popup窗体P”中的“文本框T”,然后尝试输入字符,发现无法输入。
③当焦点在WPF窗口程序外的其他地方时(如桌面上某个图标上),再鼠标点回“Popup窗体P”中的“文本框T”,然后尝试输入字符,发现无法输入。

问题参照:
当焦点在“窗体A”中时(可以“窗体A”的任意一个字控件上:如在地址栏中),鼠标点击“Popup窗体P”中的“文本框T”,然后尝试输入字符,发现可以正常输入。

问题解决方法:
通过各种消息监听,我们发现Popup虽然是个完整独立的窗体,但它的激活要靠它的“父窗口”间接来激活,这里之所以说是“父窗口”,是因为它本身并没有真正的“父窗口”,它只是从“父窗口”里产生的一个游离的“子窗口”,也就是说它没记住它的“父亲”,但是它的“父亲”倒是记住它了,在“父亲”被激活的时候,“父亲”会去主动激活它这个不肖的“儿子”,哈哈!
所以问题解决就从激活“父窗口”开始,在Popup窗体的PreviewMouseDown事件处理函数中,直接激活“父窗口”就可以了。写成伪代码如下:

xaml
<Popup PreviewMouseDown="PreviewMouseDownHandler">
……
</Popup>

xaml.cs
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
    this.Activate();
    this.SetFocus();
}



郑重声明:
除特别声明为转载内容外,本站所有内容均为作者原创,谢绝任何单位和个人不经许可的复制和转播!
对于确有转载需要的,请先与作者联系,在获得允许后烦请在转载时保留文章出处。
本文出自Lupin's Blog:http://www.cnzui.com/archives/1075