C# 通过编程将焦点设置为itemscontrol数据模板中的控件
我有一个绑定到可观察集合的headered items控件。集合中的项与数据模板相关联。数据模板非常简单,因为它只包含两个文本框。我遇到的困难是通过编程方式设置文本框的焦点 首次显示items控件时,它始终包含一个项。它可能有也可能没有绑定到第一个文本框的值。如果有值,则需要将焦点设置为第二个文本框。我使用以下方法完成了此操作:C# 通过编程将焦点设置为itemscontrol数据模板中的控件,c#,wpf,itemscontrol,C#,Wpf,Itemscontrol,我有一个绑定到可观察集合的headered items控件。集合中的项与数据模板相关联。数据模板非常简单,因为它只包含两个文本框。我遇到的困难是通过编程方式设置文本框的焦点 首次显示items控件时,它始终包含一个项。它可能有也可能没有绑定到第一个文本框的值。如果有值,则需要将焦点设置为第二个文本框。我使用以下方法完成了此操作: protected override void OnActivated(EventArgs e) { base.OnActivated(
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();
}
}
}
}
protected override void OnActivated(事件参数e)
{
碱激活(e);
如果(_激活)返回;
_激活=真;
var dc=作为MyViewModel的DataContext;
如果(null!=dc)
{
var cp=作为ContentPresenter的EntItemsControl.ItemContainerGenerator.ContainerFromIndex(0);
var tb=FindVisualChildren(cp);
如果(tb!=null)
{
如果(!String.IsNullOrEmpty(dc.TheCollection.First().FirstValue))
{
var t=tb.FirstOrDefault(box=>box.Name==“SecondTextBox”);
如果(null!=t)t.Focus();
}
其他的
{
var t=tb.FirstOrDefault(box=>box.Name==“FirstTextBox”);
如果(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();
}
}
}
public void setfocustonewithem(int索引)
{
var dc=作为MyViewModel的DataContext;
如果(null!=dc)
{
var cp=作为ContentPresenter的EntItemsControl.ItemContainerGenerator.ContainerFromIndex(索引);
var tb=FindVisualChildren(cp);
如果(tb!=null)
{
var t=tb.FirstOrDefault(box=>box.Name==“FirstTextBox”);
如果(null!=t)t.Focus();
}
}
}
添加项目后,是否有其他解决方案来设置焦点?有时,以下技巧对我很有效:
// Replace such call:
SetFocusToNewItem(newIndex);
// By this:
Dispatcher.BeginInvoke((Action) (() =>
{
SetFocusToNewItem(newIndex);
}));
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元素未创建,因此无法获取它。上面的代码延迟了函数的执行,您的方法应该在UI创建之后执行
PS:您可以在方法内部移动Dispatcher
调用
编辑:
这可能也有帮助(对我有用):
var cp=ItItemsControl.ItemContainerGenerator.ContainerFromIndex(索引)作为ContentPresenter;
已加载cp+=(s,e2)=>
{
var tb=FindVisualChildren(e2.Source作为UIElement)
.FirstOrDefault();
如果(tb!=null)
tb.Focus();
};
原因是相同的:未创建UI元素。焦点仍然不会移动到文本框。FindVisualChildren仍返回null。我似乎没有把电话耽搁得够久。更新UI时是否会引发任何事件?