首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >专注于FocusManager、ContentControl和DataTemplate

专注于FocusManager、ContentControl和DataTemplate
EN

Stack Overflow用户
提问于 2013-02-05 23:48:50
回答 1查看 1.5K关注 0票数 0

我正在尝试使用以下结构的应用程序让(键盘)焦点正常工作:

代码语言:javascript
复制
ItemsControl
  DataTemplate for Item
    ContentControl
      DataTemplate for Content (multiple, depending on type)
        Some container
          Different controls (mainly textbox or OK button should have focus)

在每个内容模板(“一些容器”)的根上,我将FocusManager.FocusedElement设置为模板中的一个控件。在ItemsControl中的所有项中,只有一个ContentControls是实际可见的(“当前”项)。因此,基本上,我使第一件事可见,其中的OK按钮具有焦点,用户可以按Enter键确认。然后这一个被隐藏,下一个被显示,并且它的主控件(例如文本框)有焦点,用户可以按enter确认(小事件处理使enter在文本框中确认该项)等等。

完成所有操作后,用户可以单击工具栏中的按钮重新开始,使第一个ContentControl再次可见。但这一次它没有焦点。我不知道谁有焦点,我希望它像一开始一样工作。我试图将焦点设置到刚刚显示的ContentControl (它可以工作,通过虚线可见),但它不会将焦点设置到它的子对象上。因为我不知道选择了哪个数据模板(好吧,不是不写特殊代码),所以我不能只是手动设置焦点或通过绑定到子对象。也许我在这一点上遗漏了一件简单的事情?

另一方面,当用户手动单击active ContentControl按钮或文本框时,他可以使用enter确认,但随后ItemsControl似乎具有焦点,而不是下一项。我就是想不通这个焦点问题。有没有简单的解决方案?我是否必须编写代码来遍历ContentControl中的树以获得正确的数据模板?然后,我是否可以只关注设置为FocusedElement的数据模板或控件,或者必须为每个数据模板单独编写代码?

EN

回答 1

Stack Overflow用户

发布于 2013-02-06 16:02:25

你应该实现一个可以在需要的时候从ViewModel触发到焦点元素的动作。尝试以下代码:

代码语言:javascript
复制
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中:

代码语言:javascript
复制
<DockPanel>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <nuib:FocusAction TargetName="title"/>
            </i:EventTrigger>
        <TextBlock x:Name="title"/>
</DockPanel>

命名空间包括:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14711391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档