聚焦失败在WPF中聚焦ItemsControls的第一个子节点

时间:2017-01-03 18:28:32

标签: c# wpf

我有一个ItemsControl,当ItemSource为null时会自动隐藏自己,并且应该在显示自己之后聚焦第一个孩子。 我通过简单地将以下处理程序添加到" IsVisibleChanged"来实现了正确的触发。事件:

if ((bool)e.NewValue)
{
    ItemsControl control = sender as ItemsControl;
    if (control != null)
    {
        control.UpdateLayout();
        Task task = Task.Run(delegate ()
            {
                while (control.Items.Count == 0 || 
                       control.ItemContainerGenerator.Status == GeneratorStatus.NotStarted ||
                       control.ItemContainerGenerator.Status == GeneratorStatus.GeneratingContainers) ;
            });

        if (await Task.WhenAny(task, Task.Delay(1000)) == task)
        {
            ContentPresenter first = control.ItemContainerGenerator.ContainerFromIndex(0) as ContentPresenter;
            if (first != null) (first.ContentTemplate.FindName("textBox", first) as System.Windows.UIElement).Focus();
        }
    }
}

处理程序在第一次显示ItemsControls时始终完美运行,但最后一行在第二次调用时抛出InvalidOperationException。

处理程序的工作方式是等待ItemContainerGenerator完成其作业(或超时一秒),然后获取ItemsControl的第一个容器,并从容器中聚焦名为" textBox&#34的元素;

如果有人能告诉我什么是错的,我会很高兴,因为唯一要执行的是if (first != null) (first.ContentTemplate.FindName("textBox", first) as System.Windows.UIElement).Focus();行。

例外消息:
此操作仅对已应用此模板的元素有效。

StackTrace:
在System.Windows.FrameworkTemplate.FindName(String name,FrameworkElement templatedParent)
在***。d__1.MoveNext()......

1 个答案:

答案 0 :(得分:0)

我找到了一种自己工作的方法,它发现问题是容器没有完全初始化,所以我更换了最后一行来检查“IsLoaded”属性并执行一些额外的工作并且还纠正了等待任务。

if ((bool)e.NewValue)
{
    ItemsControl control = sender as ItemsControl;
    if (control != null)
    {
        control.UpdateLayout();
        Task task = Task.Run(delegate ()
                    {
                        while (control.ItemContainerGenerator.Status == GeneratorStatus.NotStarted ||
                               control.ItemContainerGenerator.Status == GeneratorStatus.GeneratingContainers) ;
                    });

        if (await Task.WhenAny(task, Task.Delay(1000)) == task)
        {
            ContentPresenter first = control.ItemContainerGenerator.ContainerFromIndex(0) as ContentPresenter;
            if (first != null)
            {
                if (first.IsLoaded)
                {
                    (first.ContentTemplate.FindName("textBox", first) as System.Windows.UIElement).Focus();
                }
                else
                {
                    RoutedEventHandler onload = null;
                    onload = delegate
                    {
                        first.Loaded -= onload;
                        (first.ContentTemplate.FindName("textBox", first) as System.Windows.UIElement).Focus();
                    };
                    first.Loaded += onload;
                }
            }

        }
    }
}