zoukankan      html  css  js  c++  java
  • FocusScope学习三: 对FocusScope 的探究与总结

    http://social.msdn.microsoft.com/forums/en-US/wpf/thread/f5de6ffc-fa03-4f08-87e9-77bbad752033/

    这个帖子很好的讨论了Focus Scope的种种,WeiFen 和John给出了我最接受的总结: 我在最后也给出了我的总结:

    From WeiFen:

    I think I can explain this after digging into the framework source code.

    1. After clicking, the MenuBase and ButtonBase class will try to restore keyboard focus to previous focused element by calling Keyboard.Focus(null). This will set keyboard focus to top level main window. Since Window is a FocusScope, this will set focus to main window's FocusedElement. Normally we don't expect a click will change the focus, that's where the confusion come from. But this behavior makes sense:

    1) MenuBase works in a open-dismiss way. It should not have the focus after clicking. Actually I think they should not get focus at all, like in Win32 or Win forms. But this is another topic.

    2) Normally after clicking a button, we're not likely to click it again. So it's naturaly to restore the focus to previously focused element.

    我并没有在MSDN上查到Keyboard.Focus(null)的功能,不过既然他看了WPF源代码了,那么应噶是没错。不过假如把Window的IsFocusScope设置成false,不知道会怎么样

    2. The nested FocusScope. It's not actually that complex as we expected. Whenever an UIElement receives keyboard focus, it will find its DIRECT parent focus scope, and set this focus scope's FocusedElement to itself. Keyboard focus leaves the focus scope will do nothing.

    恩,和学习二里面相互印证(准确来说,学习二的作者读的也是WeiFeng的总结) 

    Consider the check box sample you provided:

    1) If you set IsFocusScope="true" on StackPanel, focus the check box will set StackPanel's FocusedElement to check box, and main window's FocusedElement remains unchanged - ListViewItem; After clicking the check box, because of Keyboard.Focus(null) called, the keyboard focus will set to previous ListViewItem.

    2) If you remove IsFocusScope="true" on StackPanel, focus the check box will set main window's FocusedElement to the check box. Keyboard.Focus(null) will set the focus back to the check box.

    If you want both IsFocusScope="true" and no keyboard focus change after clicking the check box, add the following code to your window class (of course you need to add x:Name="checkBox" in the XAML file):

    假如Window没有Focused Element,那么焦点则不会转移。


    protected
     override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)

    {

    base.OnGotKeyboardFocus(e);

    if (e.Source == checkBox)

    FocusManager.SetFocusedElement(this, checkBox);

    }

     

    Hope this helps,

    - Weifen

    From John:

    Wow long discussion on this...  I had to figure some of this out early on, and I thought I chip in with what I discovered.  I found some errors in the documentation that I don't think have been corrected.

    Based on my testing the correct explanation of command routing when no target is set is:

    The element within the Windows focus scope that has logical focus will be used as the command target.

    Note that it's the windows focus scope not the active focus scope.  And it's logical focus not keyboard focus.

    When it comes to command routing, FocusScopes remove any item you place them on and it's child elements from the command routing path.  

    So if you create a focus scope in your app and want a command to route in to it you will  have to set the command target manually.

    Or, you can not use FocusScopes other than for toolbars, menus etc and handle the container focus problem manually.

    The above is pretty much covered in the posts above, but I think this states it a little clearer.  If not... sorry for butting in.<g>

    HTH


    John Fenton


    From Me:


    我的测试是基于WPF4,好像他们改进了下,一下是我的总结:

    1)假如CommandSource在一个FocusScope里面,命令被触发,那么WPF会先寻找该FocusScope的事件处理程序(CommandBindings),如果有,则使用这个。我测试的是CommandBinding正好是CommandSource的Parent Container,所以不确定是不是该FocusScope的CommandBindings还是Parent Container的CommandBindings。
    2)假如主窗口有Focus Element,那么就会使用该Focus Element的Built-in的事件处理程序,假如没有,那么就是用主窗口的。假如还是没有,会找到你的FocusScope和主窗口之间的CommandBindings(直线路上,就是ParentContainer, Parent-Parent Container的,而不会找Sibling的)但是只会找CommandBindings,不会找到那些Built-in的事件处理程序。

    其实也不必太在意,真正写代码不会那么复杂的!另外 Pro WPF in C# 2010里面也讲的比较透彻,并给出了一个例子。


  • 相关阅读:
    常用正则表达式
    偶得
    监控文件夹里面文件修改的小程序
    使用Windows服务发布WCF服务
    查看wcf服务中方法测试客户端
    twitter注册使用指南
    打包工具使用下载
    c#多线程编程
    请确保此文件可访问并且是一个有效的程序集或COM组件
    添加Service Reference, 无法为服务生成代码错误的解决办法
  • 原文地址:https://www.cnblogs.com/puncha/p/3877003.html
Copyright © 2011-2022 走看看