当前位置:  开发笔记 > 编程语言 > 正文

WPF和初始焦点

如何解决《WPF和初始焦点》经验,为你挑选了7个好方法。

似乎当WPF应用程序启动时,没有任何焦点.

这真的很奇怪.我使用的每个其他框架都符合您的期望:将初始焦点放在Tab键顺序中的第一个控件上.但我已经确认它是WPF,而不仅仅是我的应用程序 - 如果我创建一个新窗口,只是在其中放置一个TextBox,并运行应用程序,TextBox没有焦点,直到我点击它或按Tab键.呸.

我的实际应用程序比TextBox更复杂.我在UserControls中有几层UserControl.其中一个UserControls有Focusable ="True"和KeyDown/KeyUp处理程序,我希望它在我的窗口打开后立即获得焦点.不过,我仍然是一个WPF新手,而且我没有太多运气搞清楚如何做到这一点.

如果我启动我的应用程序并按Tab键,则焦点转到我的可聚焦控件,它开始以我想要的方式工作.但我不希望我的用户在开始使用窗口之前必须点击Tab.

我已经使用了FocusManager.FocusedElement,但是我不确定将它设置为哪个控件(顶级窗口?包含可聚焦控件的父级?可聚焦控件本身?)或者设置它的内容.

在窗口打开后,我需要做什么才能使我的深层嵌套控件具有初始焦点?或者更好的是,将第一个可聚焦控件聚焦在Tab键顺序中?



1> Joe White..:

我有一个聪明的主意,就是通过Reflector来查看Focusable属性的使用位置,并找到了解决这个问题的方法.我只需要将以下代码添加到我的Window的构造函数中:

Loaded += (sender, e) =>
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

这将自动选择Tab键顺序中的第一个控件,因此它是一个通用的解决方案,应该可以放入任何窗口和Just Work.


将其转换为行为. ...
@wekempf,我不熟悉行为的概念,但我调查了它,这根本不是一个坏主意.如果其他人(像我一样)还不熟悉附加的行为,这里有一个解释:http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx

2> 小智..:

这也有效:



   
     ...
   


似乎在UserControls中不起作用.
我很惊讶我是第一个对此发表评论的人.我很困惑,因为它几乎可以进行任何控制.在回答这个具体问题,我觉得它会去的窗口,但你可以阅读http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager%28v=vs的言论.110%29.aspx了解您如何控制此事.

3> Mizipzor..:

基于作为附加行为实现的已接受答案:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace UI.Behaviors
{
    public static class FocusBehavior
    {
        public static readonly DependencyProperty FocusFirstProperty =
            DependencyProperty.RegisterAttached(
                "FocusFirst",
                typeof(bool),
                typeof(FocusBehavior),
                new PropertyMetadata(false, OnFocusFirstPropertyChanged));

        public static bool GetFocusFirst(Control control)
        {
            return (bool)control.GetValue(FocusFirstProperty);
        }

        public static void SetFocusFirst (Control control, bool value)
        {
            control.SetValue(FocusFirstProperty, value);
        }

        static void OnFocusFirstPropertyChanged(
            DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Control control = obj as Control;
            if (control == null || !(args.NewValue is bool))
            {
                return;
            }

            if ((bool)args.NewValue)
            {
                control.Loaded += (sender, e) =>
                    control.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            }
        }
    }
}

像这样使用它:



在我看来,这是*到目前为止*我找到的最佳解决方案.谢谢!

4> Joe White..:

我找到了另一种可能的解 Mark Smith发布了一个FirstFocusedElement标记扩展,用于与FocusManager.FocusedElement一起使用.




5> OrPaz..:

在进行了"WPF初始焦点噩梦"并基于堆栈上的一些答案后,以下证明我是最佳解决方案.

首先,添加您的App.xaml OnStartup()以下内容:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

然后在App.xaml中添加'WindowLoaded'事件:

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

必须使用线程问题,因为WPF的初始焦点主要是由于某些框架竞争条件而失败.

我发现以下解决方案最好,因为它在整个应用程序中全局使用.

希望能帮助到你...

奥兰


使用`BeginInvoke`而不是那个可怕的`Sleep(100)`语句.

6> Vladik Y..:

有同样的问题用简单的解决方案解决了它:在主窗口中:

  

在用户控件中:

private void UserControl_GotFocus_1(object sender, RoutedEventArgs e)
        {
            targetcontrol.Focus();
            this.GotFocus -= UserControl_GotFocus_1;  // to set focus only once
        }


仅当控件直接位于Window内时才有效,而不是嵌套在UserControl中.

7> Simon Gillbe..:

您可以轻松地将控件设置为XAML中的焦点元素.


   
     ...
   

我从来没有尝试在用户控件中设置它,看看它是否有效,但它可能.

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有