我有UserControl
,其中包含TextBox
。当我的主窗口加载时,我想将焦点设置为此文本框,因此我将Focusable="True" GotFocus="UC_GotFocus"
添加到UserControl
的定义,并将FocusManager.FocusedElement="{Binding ElementName=login}"
添加到我的主窗口定义中。在UC_GotFocus
方法中,我只需在我想要关注的控件上调用.Focus()
,但这不起作用。
我需要做的就是在应用程序启动时TextBox
获得焦点UserControl
。
任何帮助都将不胜感激,谢谢。
答案 0 :(得分:26)
我最近修复了这个问题,因为当首次加载主窗口时,通过故事板显示登录启动画面。
我相信修复有两个关键。一个是使包含元素成为焦点范围。另一个是处理由加载窗口触发的故事板的Storyboard Completed事件。
此故事板使用户名和密码画布可见,然后逐渐变为100%不透明。关键是在故事板运行之前,用户名控件不可见,因此该控件在可见之前无法获得键盘焦点。让我离开一段时间的是它有“焦点”(即焦点是真的,但事实证明这只是逻辑焦点)并且我不知道WPF在阅读Kent Boogaart之前有逻辑和键盘焦点的概念回答并查看Microsoft的WPF link text
一旦我这样做,我的特定问题的解决方案很简单:
1)使包含元素成为焦点范围
<Canvas FocusManager.IsFocusScope="True" Visibility="Collapsed">
<TextBox x:Name="m_uxUsername" AcceptsTab="False" AcceptsReturn="False">
</TextBox>
</Canvas>
2)将完成的事件处理程序附加到故事板
<Storyboard x:Key="Splash Screen" Completed="UserNamePassword_Storyboard_Completed">
...
</Storyboard>
和
3)设置我的用户名TextBox,使键盘焦点在storyboard completed事件处理程序中。
void UserNamePassword_Storyboard_Completed(object sender, EventArgs e)
{
m_uxUsername.Focus();
}
请注意,调用item.Focus()会导致调用Keyboard.Focus(this),因此您无需显式调用它。请参阅有关difference between Keyboard.Focus(item) and item.Focus.
的此问题答案 1 :(得分:16)
它很愚蠢,但确实有效:
弹出等待一段时间的线程,然后返回并设置您想要的焦点。它甚至可以在元素主机的上下文中工作。
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();
}));
}
);
}
答案 2 :(得分:7)
就在最近,我有一个包含一些TextBlocks的列表框。我希望能够双击文本块并将其转换为TextBox,然后专注于它并选择所有文本,以便用户可以开始键入新名称(类似于Adobe图层)
无论如何,我是通过一个活动做到这一点而且它不起作用。我这里的神奇子弹是确保我将事件设置为处理。我认为它是设置焦点,但是一旦事件发生故障,它就会切换逻辑焦点。
故事的寓意是,确保你将事件标记为已处理,这可能是你的问题。
答案 3 :(得分:6)
“在应用程序启动时设置初始焦点时,接收焦点的元素必须连接到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();
}
答案 4 :(得分:5)
因为我尝试了一个fuzquat的解决方案并发现它是最通用的解决方案,我想我会分享一个不同的版本,因为有些人抱怨它看起来很乱。所以这是:
casted.Dispatcher.BeginInvoke(new Action<UIElement>(x =>
{
x.Focus();
}), DispatcherPriority.ApplicationIdle, casted);
没有Thread.Sleep,没有ThreadPool。我希望足够清洁。真的可以使用一些代表,所以我可以评论其他人的解决方案。
更新:
因为人们似乎喜欢漂亮的代码:
public static class WpfExtensions
{
public static void BeginInvoke<T>(this T element, Action<T> action, DispatcherPriority priority = DispatcherPriority.ApplicationIdle) where T : UIElement
{
element.Dispatcher.BeginInvoke(priority, action);
}
}
现在你可以这样称呼它:
child.BeginInvoke(d => d.Focus());
答案 5 :(得分:4)
我发现了一系列关于WPF焦点的博客文章。
它们都很好阅读,但第3部分专门处理将焦点设置为UserControl中的UI元素。
答案 6 :(得分:3)
WPF支持两种不同的焦点:
FocusedElement
属性获取或设置焦点范围内的逻辑焦点。我怀疑您的TextBox
具有逻辑焦点,但其包含的焦点范围不是主动焦点范围。因此,它 没有键盘焦点。
所以问题是,你的可视化树中有多个焦点范围吗?
答案 7 :(得分:3)
在我输入时,我有一个使用此解决方案运行的示例应用。如果这对您不起作用,则必须存在导致问题的应用或环境特定的内容。在您的原始问题中,我认为绑定导致问题。 我希望这会有所帮助。
答案 8 :(得分:1)
我将fuzquat的答案转换为扩展方法。我正在使用它而不是Focus(),其中Focus()不起作用。
var node = list.Cast<XmlNode>()
.Where(n => n.Attributes["id"].InnerText == "abc")
.Select(x => x.Attributes["abv"].InnerText);
答案 9 :(得分:1)
对我来说,诀窍是 FocusManager.FocusedElement 属性。我首先尝试在UserControl上设置它,但它不起作用。
所以我尝试将它放在UserControl的第一个孩子身上:
<UserControl x:Class="WpfApplication3.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid FocusManager.FocusedElement="{Binding ElementName=MyTextBox, Mode=OneWay}">
<TextBox x:Name="MyTextBox"/>
</Grid>
......它有效! :)
答案 10 :(得分:1)
在'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的初始焦点主要是由于某些框架竞争条件而失败。
我发现以下解决方案最佳,因为它在整个应用程序中全局使用。
希望它有所帮助...
奥兰
答案 11 :(得分:1)
我注意到一个焦点问题,特别是在ElementHosts中托管WPF UserControls,它包含在一个Form中,该Form通过MdiParent属性设置为MDI子级。
我不确定这是否与其他人遇到的问题相同,但您可以通过以下链接深入了解详情。
答案 12 :(得分:0)
假设您要为Username文本框设置焦点,因此用户可以在每次显示时直接输入。
在您的控件的构造函数中:
this.Loaded += (sender, e) => Keyboard.Focus(txtUsername);
答案 13 :(得分:0)
在尝试上述建议的组合之后,我能够使用以下内容可靠地将焦点分配给子UserControl上的所需文本框。基本上,将焦点放在子控件上,让子UserControl将焦点放在TextBox上。 TextBox的焦点语句本身返回true,但是在UserControl也被赋予焦点之前没有产生所需的结果。我还应该注意到,UserControl无法为自己请求焦点,必须由Window提供。
为简洁起见,我省略了在Window和UserControl上注册Loaded事件。
窗口
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
ControlXYZ.Focus();
}
用户控件
private void OnControlLoaded(object sender, RoutedEventArgs e)
{
TextBoxXYZ.Focus();
}
答案 14 :(得分:0)
我在PageLoaded()或控件加载中设置它,但后来我正在调用WCF异步服务并做一些似乎失去焦点的东西。我必须在我做的所有事情的最后设置它。这很好,但有时我会对代码进行更改,然后我忘记了我也在设置光标。
答案 15 :(得分:0)
我有用户控件 - 带有两个文本框的堆栈面板。文本框是在构造函数中添加的,而不是在xaml中。当我尝试聚焦第一个文本框时,没有任何事情发生。 使用Loaded事件的siggestion修复了我的问题。刚刚在Loaded事件和everthing中调用control.Focus()。
答案 16 :(得分:0)
我不喜欢为UserControl设置另一个标签范围的解决方案。在这种情况下,当您通过键盘导航时,您将有两个不同的插入符号:在窗口上,另一个 - 在用户控件内部。我的解决方案只是将焦点从用户控件重定向到内部子控件。将用户控件设置为可聚焦(因为默认情况下为false):
<UserControl ..... Focusable="True">
并覆盖代码隐藏中的焦点事件处理程序:
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
MyTextBox.Focus();
}
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
Keyboard.Focus(MyTextBox);
}
答案 17 :(得分:-2)
我在WPF用户控件中将键盘焦点设置为画布时遇到了同样的问题。 我的解决方案
Focusable="True"
在element_mousemove
事件中创建简单检查:
if(!element.IsKeyBoardFocused)
element.Focus();
就我而言,它运作良好。