我有一个绑定到可观察集合的带标题的项控件。集合中的项目与数据模板相关联。数据模板非常简单,因为它只包含两个文本框。我遇到困难的部分是以编程方式将焦点设置到文本框。
首次显示项目控件时,它始终包含一个项目。它可能有也可能没有绑定到第一个文本框的值。如果它有值,则需要将焦点设置为第二个文本框。我使用以下方法完成了这项工作:
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
if (_activated) return;
_activated = true;
var dc = DataContext as MyViewModel;
if (null != dc)
{
var cp = theItemsControl.ItemContainerGenerator.ContainerFromIndex(0) as ContentPresenter;
var tb = FindVisualChildren<TextBox>(cp);
if (tb != null)
{
if (!String.IsNullOrEmpty(dc.TheCollection.First().FirstValue))
{
var t = tb.FirstOrDefault(box => box.Name == "SecondTextBox");
if (null != t) t.Focus();
}
else
{
var t = tb.FirstOrDefault(box => box.Name == "FirstTextBox");
if (null != t) t.Focus();
}
}
}
}
这似乎工作正常。但是,现在,当一个新项添加到集合时,我需要将焦点设置为FirstTextBox。我已尝试使用FocusManager在datatemplate中设置焦点,但这禁止上述代码正常工作。我也在视图中尝试了以下内容。将新项添加到ObservableCollection后,将从ViewModel调用该方法。代码运行,但无法找到任何文本框(即.tb == null)。是否已在此时创建控件?
public void SetFocusToNewItem(int index)
{
var dc = DataContext as MyViewModel;
if (null != dc)
{
var cp = theItemsControl.ItemContainerGenerator.ContainerFromIndex(index) as ContentPresenter;
var tb = FindVisualChildren<TextBox>(cp);
if (tb != null)
{
var t = tb.FirstOrDefault(box => box.Name == "FirstTextBox");
if (null != t) t.Focus();
}
}
}
在添加项目后是否还有其他解决方案来设置焦点?
答案 0 :(得分:0)
有时以下技巧对我有用:
// Replace such call:
SetFocusToNewItem(newIndex);
// By this:
Dispatcher.BeginInvoke((Action) (() =>
{
SetFocusToNewItem(newIndex);
}));
问题是当您在集合中添加项目时,未创建UI元素,因此您无法获取它。上面的代码会延迟执行函数,并且应该在创建UI后执行该方法。
PS:您可以在方法中移动Dispatcher
来电。
修改强>:
这也有帮助(对我有用):
var cp = theItemsControl.ItemContainerGenerator.ContainerFromIndex(index) as ContentPresenter;
cp.Loaded += (s, e2) =>
{
var tb = FindVisualChildren<TextBox>(e2.Source as UIElement)
.FirstOrDefault();
if (tb != null)
tb.Focus();
};
原因是相同的:未创建UI元素。