C# 通过编程将焦点设置为itemscontrol数据模板中的控件

C# 通过编程将焦点设置为itemscontrol数据模板中的控件,c#,wpf,itemscontrol,C#,Wpf,Itemscontrol,我有一个绑定到可观察集合的headered items控件。集合中的项与数据模板相关联。数据模板非常简单,因为它只包含两个文本框。我遇到的困难是通过编程方式设置文本框的焦点 首次显示items控件时,它始终包含一个项。它可能有也可能没有绑定到第一个文本框的值。如果有值,则需要将焦点设置为第二个文本框。我使用以下方法完成了此操作: protected override void OnActivated(EventArgs e) { base.OnActivated(

我有一个绑定到可观察集合的headered items控件。集合中的项与数据模板相关联。数据模板非常简单,因为它只包含两个文本框。我遇到的困难是通过编程方式设置文本框的焦点

首次显示items控件时,它始终包含一个项。它可能有也可能没有绑定到第一个文本框的值。如果有值,则需要将焦点设置为第二个文本框。我使用以下方法完成了此操作:

    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时是否会引发任何事件?