我正在尝试通过以下结构的应用程序使(键盘)焦点正常工作:
ItemsControl
DataTemplate for Item
ContentControl
DataTemplate for Content (multiple, depending on type)
Some container
Different controls (mainly textbox or OK button should have focus)
在每个内容模板的根目录(“Some container”)上,我将FocusManager.FocusedElement
设置为模板中的一个控件。 ItemsControl中的所有项目中,只有一个ContentControl实际可见(“当前”)。所以,基本上,我首先看到它,其中的OK按钮有焦点,用户可以按Enter确认。然后隐藏这一个,显示下一个,并且其主控件(例如文本框)具有焦点,用户可以按回车确认(小事件处理使文本框中的输入确认该项目)等等。 / p>
完成所有操作后,用户可以单击工具栏中的按钮重新开始,使第一个ContentControl再次可见。但这一次它没有焦点。我不知道谁有焦点,我希望它像开始时一样工作。我试图将焦点设置为刚刚显示的ContentControl(通过虚线可见),但它不会将焦点设置为它的子节点。由于我不知道选择了哪个数据模板(好吧,不是没有编写特殊代码),我不能手动设置焦点或通过绑定到子节点。也许我现在错过了一件简单的事情?
另一方面,当用户手动点击活动的ContentControl按钮或文本框时,他可以使用回车确认,但是然后ItemsControl似乎有焦点,而不是下一个项目。我无法理解这个焦点的事情。有简单的解决方案吗?我是否必须编写代码来从ContentControl遍历树以获取正确的datatemplate?然后,我可以只关注数据模板或设置为FocusedElement的控件,还是必须分别为每个数据模板编写代码?
答案 0 :(得分:0)
您应该实现一个动作,可以在需要时从ViewModel触发焦点元素。试试这段代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interactivity;
using System.Windows;
namespace Behaviors
{
/// <summary>
/// Action to focus target element, if invoked when target is not yet specified, will focus once the target is set
/// </summary>
public class FocusAction : TargetedTriggerAction<DependencyObject>
{
protected override void OnAttached()
{
base.OnAttached();
}
protected override void OnDetaching()
{
base.OnDetaching();
}
protected override void Invoke(object parameter)
{
if (Target is UIElement)
{
if(!((UIElement)Target).IsKeyboardFocusWithin)
((UIElement)Target).Focus();
}
else
invokeOnConnect = true;
}
private bool invokeOnConnect = false;
protected override void OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)
{
base.OnTargetChanged(oldTarget, newTarget);
if (invokeOnConnect)
{
invokeOnConnect = false;
Invoke(null);
}
}
}
}
然后在WPF中:
<DockPanel>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<nuib:FocusAction TargetName="title"/>
</i:EventTrigger>
<TextBlock x:Name="title"/>
</DockPanel>
名称空间是:
xmlns:nuib="clr-namespace:Behaviors;assembly=Nui" // for Action class
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" // .net library for interactivity