无法将焦点设置到 UserControl 的子级
我有一个UserControl
,其中包含一个TextBox
。 当我的主窗口加载时,我想将焦点设置到此文本框,因此我将 Focusable="True" GotFocus="UC_GotFocus"
添加到 UserControl
的定义和 FocusManager.FocusedElement="{Binding ElementName=login}"
到我的主窗口定义。 在 UC_GotFocus
方法中,我只需在我想要关注的控件上调用 .Focus()
,但这不起作用。
我需要做的就是让 UserControl
中的 TextBox
在应用程序启动时接收焦点。
任何帮助将不胜感激,谢谢。
I have a UserControl
which contains a TextBox
. When my main window loads I want to set the focus to this textbox so I added Focusable="True" GotFocus="UC_GotFocus"
to the UserControl
s definition and FocusManager.FocusedElement="{Binding ElementName=login}"
to my main windows definition. In the UC_GotFocus
method i simply call .Focus()
on the control i want to focus on but this doesn't work.
All i need to do is have a TextBox
in a UserControl
receive focus when the application starts.
Any help would be appreciated, thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
我最近修复了首次加载主窗口时通过故事板显示的登录初始屏幕的问题。
我相信解决这个问题有两个关键。 一种是使包含元素成为焦点范围。 另一个是处理由正在加载的窗口触发的故事板的 Storyboard Completed 事件。
此故事板使用户名和密码画布可见,然后逐渐变为 100% 不透明。 关键是用户名控件在故事板运行之前不可见,因此该控件在可见之前无法获得键盘焦点。 让我有一段时间感到困惑的是它有“焦点”(即焦点是正确的,但事实证明这只是逻辑焦点),直到阅读 Kent Boogaart 的文章之前我并不知道 WPF 具有逻辑焦点和键盘焦点的概念回答并查看 Microsoft 的 WPF 链接文本
一旦我这样做了解决方案对于我的特定问题来说很简单:
1)使包含元素成为焦点范围
2)将完成的事件处理程序附加到故事板
3
)设置我的用户名TextBox以使键盘焦点位于故事板完成的事件处理程序中。
请注意,调用 item.Focus() 会导致调用 Keyboard.Focus(this),因此您不需要显式调用它。 请参阅有关 Keyboard.Focus(item) 和项目.焦点。
I recently fixed this problem for a login splash screen that is being displayed via a storyboard when the main window is first loaded.
I believe there were two keys to the fix. One was to make the containing element a focus scope. The other was to handle the Storyboard Completed event for the storyboard that was triggered by the window being loaded.
This storyboard makes the username and password canvas visible and then fades into being 100% opaque. The key is that the username control was not visible until the storyboard ran and therefore that control could not get keyboard focus until it was visible. What threw me off for awhile was that it had "focus" (i.e. focus was true, but as it turns out this was only logical focus) and I did not know that WPF had the concept of both logical and keyboard focus until reading Kent Boogaart's answer and looking at Microsoft's WPF link text
Once I did that the solution for my particular problem was straightforward:
1) Make the containing element a focus scope
2) Attach a Completed Event Handler to the Storyboard
and
3) Set my username TextBox to have the keyboard focus in the storyboard completed event handler.
Note that calling item.Focus() results in the call Keyboard.Focus(this), so you don't need to call this explicitly. See this question about the difference between Keyboard.Focus(item) and item.Focus.
它很愚蠢,但很有效:
弹出一个线程,等待一段时间,然后返回并设置您想要的焦点。 它甚至可以在元素宿主的上下文中工作。
Its stupid but it works:
Pop a thread that waits a while then comes back and sets the focus you want. It even works within the context of an element host.
就在最近,我有一个包含一些文本块的列表框。 我希望能够双击文本块并将其变成文本框,然后将焦点放在它上并选择所有文本,以便用户可以开始输入新名称(类似于 Adobe Layers)
无论如何,我正在做这与一个事件有关,但它不起作用。 对我来说,最重要的是确保我将事件设置为要处理的。 我认为它正在设置焦点,但是一旦事件沿着路径走下去,它就会切换逻辑焦点。
这个故事的寓意是,确保您将事件标记为已处理,这可能是您的问题。
Just recently I had a list-box that housed some TextBlocks. I wanted to be able to double click on the text block and have it turn into a TextBox, then focus on it and select all the text so the user could just start typing the new name (Akin to Adobe Layers)
Anyway, I was doing this with an event and it just wasn't working. The magic bullet for me here was making sure that I set the event to handled. I figure it was setting focus, but as soon as the event went down the path it was switching the logical focus.
The moral of the story is, make sure you're marking the event as handled, that might be your issue.
(MSDN)
只需在 Window(或 Control)的构造函数中添加一个“Loaded”事件处理程序,然后在该事件处理程序中调用目标控件上的 Focus() 方法即可。
(MSDN)
Simply add a "Loaded" event handler in the constructor of your Window (or Control), and in that event handler call the Focus() method on the target control.
因为我尝试了 fuzquat 的解决方案并发现它是最通用的解决方案,所以我想我应该分享一个不同的版本,因为有些人抱怨它看起来很混乱。 所以这里是:
没有 Thread.Sleep,没有 ThreadPool。 我希望足够干净。
更新:
由于人们似乎喜欢漂亮的代码:
现在你可以这样调用它:
since i tried a fuzquat's solution and found it the most generic one, i thought i'd share a different version, since some complained about it looking messy. so here it is:
no Thread.Sleep, no ThreadPool. Clean enough i hope.
UPDATE:
Since people seem to like pretty code:
now you can call it like this:
WPF 支持两种不同类型的焦点:
FocusedElement
属性获取或设置焦点范围内的逻辑焦点。 我怀疑您的TextBox
确实 具有逻辑焦点,但其包含焦点范围不是活动焦点范围。 因此,它没有键盘焦点。所以问题是,您的视觉树中是否有多个焦点范围?
WPF supports two different flavors of focus:
The
FocusedElement
property gets or sets logical focus within a focus scope. I suspect yourTextBox
does have logical focus, but its containing focus scope is not the active focus scope. Ergo, it does not have keyboard focus.So the question is, do you have multiple focus scopes in your visual tree?
我发现了一系列关于 WPF focus 的好博客文章。
它们都很好读,但第三部分专门处理将焦点设置到 UserControl 中的 UI 元素。
I found a good series of blog posts on WPF focus.
They are all good to read, but the 3rd part specifically deals with setting focus to a UI element in a UserControl.
Focusable="True"
(XAML)GotFocus
事件并调用yourTextBox.Focus()
Loaded
事件并调用yourControl.Focus()
我在键入时使用此解决方案运行一个示例应用程序。 如果这对您不起作用,则一定有特定于您的应用程序或环境的因素导致了问题。 在你原来的问题中,我认为绑定是导致问题的原因。
我希望这有帮助。
Focusable="True"
(XAML)GotFocus
event on your control and callyourTextBox.Focus()
Loaded
event on your window and callyourControl.Focus()
I have a sample app running with this solution as I type. If this does not work for you, there must be something specific to your app or environment that causes the problem. In your original question, I think the binding is causing the problem.
I hope this helps.
在经历了“WPF 初始焦点噩梦”并基于堆栈上的一些答案之后,以下内容对我来说是最好的解决方案。
首先,添加您的 App.xaml OnStartup() 以下内容:
然后也在 App.xaml 中添加“WindowLoaded”事件:
必须使用线程问题,因为 WPF 初始焦点大多由于某些框架竞争条件而失败。
我发现以下解决方案最好,因为它在整个应用程序中全局使用。
希望它有帮助...
奥兰
After having a 'WPF Initial Focus Nightmare' and based on some answers on stack, the following proved for me to be the best solution.
First, add your App.xaml OnStartup() the followings:
Then add the 'WindowLoaded' event also in App.xaml :
The threading issue must be use as WPF initial focus mostly fails due to some framework race conditions.
I found the following solution best as it is used globally for the whole app.
Hope it helps...
Oran
对我来说,窍门是 FocusManager.FocusedElement 属性。 我首先尝试在 UserControl 上设置它,但没有成功。
所以我尝试将它放在 UserControl 的第一个子控件上:
...并且成功了! :)
What did the trick for me was the FocusManager.FocusedElement attribute. I first tried to set it on the UserControl, but it didn't work.
So I tried putting it on the UserControl's first child instead:
... and it worked! :)
我将 fuzquat 的答案转换为扩展方法。 我使用这个而不是 Focus() ,其中 Focus() 不起作用。
I converted fuzquat's answer to an extension method. I'm using this instead of Focus() where Focus() did not work.
我注意到一个与在 ElementHosts 中托管 WPF UserControls 特别相关的焦点问题,这些控件包含在通过 MdiParent 属性设置为 MDI 子项的 Form 中。
我不确定这是否与其他人遇到的问题相同,但您可以通过以下链接深入了解详细信息。
在 a 中设置焦点的问题WPF UserControl 托管在 WindowsForms 子 MDI 表单中的 ElementHost
I've noticed a focus issue specifically related to hosting WPF UserControls within ElementHosts which are contained within a Form that is set as an MDI child via the MdiParent property.
I'm not sure if this is the same issue others are experiencing but you dig into the details by following the link below.
Issue with setting focus within a WPF UserControl hosted within an ElementHost in a WindowsForms child MDI form
我不喜欢为 UserControl 设置另一个选项卡范围的解决方案。 在这种情况下,通过键盘导航时,您将有两个不同的插入符:在窗口上,另一个在用户控件内。 我的解决方案只是将焦点从用户控件重定向到内部子控件。 设置用户控件可聚焦(因为默认情况下为 false):
并覆盖代码隐藏中的焦点事件处理程序:
I don't like solutions with setting another tab scope for UserControl. In that case, you will have two different carets when navigating by keyboard: on the window and the another - inside user control. My solution is simply to redirect focus from user control to inner child control. Set user control focusable (because by default its false):
and override focus events handlers in code-behind:
我有用户控件 - 带有两个文本框的堆栈面板。文本框是在构造函数中添加的,而不是在 xaml 中。 当我尝试聚焦第一个文本框时,什么也没有发生。
Loaded 事件的 suggestion 解决了我的问题。 只是在 Loaded 事件和其他事件中调用 control.Focus() 。
I have user control - stack panel with two text boxes.The text boxes were added in contructor, not in the xaml. When i try to focus first text box, nothing happend.
The siggestion with Loaded event fix my problem. Just called control.Focus() in Loaded event and everthing.
假设您想为用户名文本框设置焦点,以便用户可以在每次显示时直接输入。
在您的控件的构造函数中:
Assuming you want to set focus for Username textbox, thus user can type in directly every time it shows up.
In Constructor of your control:
在尝试上述建议的组合后,我能够使用以下内容可靠地将焦点分配给子 UserControl 上的所需文本框。 基本上,将焦点赋予子控件,并让子 UserControl 将焦点赋予其 TextBox。 TextBox 的 focus 语句本身返回 true,但是直到 UserControl 也获得焦点后才产生所需的结果。 我还应该注意到,UserControl 无法为自己请求焦点,必须由 Window 提供。
为了简洁起见,我省略了在 Window 和 UserControl 上注册 Loaded 事件。
窗口
用户控件
After trying combinations of the suggestions above, I was able to reliably assign focus to a desired text box on a child UserControl with the following. Basically, give focus to the child control and have the child UserControl give focus to its TextBox. The TextBox's focus statement returned true by itself, however did not yield the desired result until the UserControl was given focus as well. I should also note that the UserControl was unable to request focus for itself and had to be given by the Window.
For brevity I left out registering the Loaded events on the Window and UserControl.
Window
UserControl
我将其设置在 PageLoaded() 或加载的控件中,但随后我调用 WCF 异步服务并执行似乎失去焦点的操作。 我必须将它设置在我所做的所有事情的末尾。 这很好,但有时我对代码进行了更改,然后我忘记了我也在设置光标。
I set it in the PageLoaded() or control loaded, but then I'm calling WCF async service and doing stuff that seems to lose the focus. I have to to set it at the end of all the stuff I do. That's fine and all, but sometimes I make changes to the code and then I forget that I'm also setting the cursor.
我在 WPF 用户控件中将键盘焦点设置为画布时遇到了同样的问题。
我的解决方案
Focusable="True"
在
element_mousemove
事件中创建简单检查:就我而言,它工作正常。
I had same problem with setting keyboard focus to canvas in WPF user control.
My solution
Focusable="True"
In
element_mousemove
event create simple check:In my case it works fine.