我有一个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()......
答案 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;
}
}
}
}
}