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

无法将焦点设置为UserControl的子节点

如何解决《无法将焦点设置为UserControl的子节点》经验,为你挑选了5个好方法。

我有一个UserControl包含一个TextBox.当我的主窗口加载时,我想将焦点设置到此文本框,所以我添加Focusable="True" GotFocus="UC_GotFocus"UserControls定义和FocusManager.FocusedElement="{Binding ElementName=login}"我的主窗口定义.在UC_GotFocus方法中,我只是调用.Focus()我想要关注的控件,但这不起作用.

我需要做的就是在应用程序启动时有TextBox一个UserControl接收焦点.

任何帮助将不胜感激,谢谢.



1> eesh..:

我最近修复了这个问题,因为登录初始屏幕是在首次加载主窗口时通过故事板显示的.

我相信修复有两个关键.一个是使包含元素成为焦点范围.另一个是处理由加载窗口触发的故事板的Storyboard Completed事件.

此故事板使用户名和密码画布可见,然后淡入100%不透明.关键是在故事板运行之前,用户名控件是不可见的,因此该控件在可见之前无法获得键盘焦点.让我离开一段时间的是它有"焦点"(即焦点是真的,但事实证明这只是逻辑焦点)并且我不知道WPF在阅读Kent Boogaart之前有逻辑和键盘焦点的概念回答并查看Microsoft的WPF 链接文本

一旦我这样做,我的特定问题的解决方案是直截了当的:

1)使包含元素成为焦点范围


    
    

2)将完成的事件处理程序附加到故事板

    
...

3)设置我的用户名TextBox,使键盘焦点在storyboard完成的事件处理程序中.

void UserNamePassword_Storyboard_Completed(object sender, EventArgs e)
{
 m_uxUsername.Focus();
}

请注意,调用item.Focus()会导致调用Keyboard.Focus(this),因此您无需显式调用它.看到这个关于Keyboard.Focus(item)和item.Focus之间区别的问题.



2> 小智..:

它的愚蠢,但它的工作原理:

弹出等待一段时间的线程然后返回并设置您想要的焦点.它甚至可以在元素主机的上下文中工作.

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{

 System.Threading.ThreadPool.QueueUserWorkItem(
                   (a) =>
                        {
                            System.Threading.Thread.Sleep(100);
                            someUiElementThatWantsFocus.Dispatcher.Invoke(
                            new Action(() =>
                            {
                                someUiElementThatWantsFocus.Focus();

                            }));
                        }
                   );

}



3> Vassi..:

就在最近,我有一个包含一些TextBlocks的列表框.我希望能够双击文本块并将其转换为TextBox,然后专注于它并选择所有文本,以便用户可以开始键入新名称(类似于Adobe图层)

无论如何,我正在做一个事件,它只是没有工作.我这里的神奇子弹是确保我将事件设置为处理.我认为它设置焦点,但是一旦事件沿着路径向下切换逻辑焦点.

这个故事的寓意是,确保你把事件标记为已处理,这可能是你的问题.



4> David..:

"在应用程序启动时设置初始焦点时,接收焦点的元素必须连接到PresentationSource,并且元素必须将Focusable和IsVisible设置为true.建议初始焦点的建议位置是"已加载的事件处理程序"(MSDN)

只需在Window(或Control)的构造函数中添加一个"Loaded"事件处理程序,并在该事件处理程序中调用目标控件上的Focus()方法.

    public MyWindow() {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(MyWindow_Loaded);
    }

    void MyWindow_Loaded(object sender, RoutedEventArgs e) {
        textBox.Focus();
    }



5> Dbl..:

因为我尝试了一个fuzquat的解决方案,并发现它是最通用的,我想我会分享一个不同的版本,因为一些人抱怨它看起来很乱.所以这里是:

                casted.Dispatcher.BeginInvoke(new Action(x =>
                {
                    x.Focus();
                }), DispatcherPriority.ApplicationIdle, casted);

没有Thread.Sleep,没有ThreadPool.我希望足够清洁.真的可以使用一些代表,所以我可以评论其他人的解决方案.

更新:

因为人们似乎喜欢漂亮的代码:

public static class WpfExtensions
{
    public static void BeginInvoke(this T element, Action action, DispatcherPriority priority = DispatcherPriority.ApplicationIdle) where T : UIElement
    {
        element.Dispatcher.BeginInvoke(priority, action);
    }
}

现在你可以像这样调用它:

child.BeginInvoke(d => d.Focus());

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