检索动态创建的TextBox元素并将其聚焦

时间:2010-05-07 16:52:26

标签: c# wpf listview textbox datatemplate

我有一个自定义类型VariableValueViewModel的集合(VariableValueCollection)  用ListView绑定的对象。 WPF关注:

<ListView ItemsSource="{Binding VariableValueCollection}" Name="itemList">
    <ListView.Resources>
        <DataTemplate DataType="{x:Type vm:VariableValueViewModel}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="180"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBox TabIndex="{Binding Path=Index, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Grid.Column="0" Name="tbValue" Focusable="True" LostFocus="tbValue_LostFocus" GotFocus="tbValue_GotFocus" KeyDown="tbValue_KeyDown">
                    <TextBox.Text>
                        <Binding Path="Value" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
                            <Binding.ValidationRules>
                                <ExceptionValidationRule></ExceptionValidationRule>
                            </Binding.ValidationRules>
                                </Binding>
                     </TextBox.Text>
                </TextBox>                            
             </Grid>
         </DataTemplate>
     </ListView.Resources>
 </ListView>

我的目标是在最后一行按“enter”时添加一个新行,然后将新行聚焦。为此,我检查该行是最后一行,并在这种情况下添加一行。但我不知道如何关注新的TextBox ......

这里是KeyPressed方法:

private void tbValue_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Enter)
        {

            DependencyObject obj = itemList.ContainerFromElement((sender as TextBox));                
            int index = itemList.ItemContainerGenerator.IndexFromContainer(obj);
            if( index ==  (VariableValueCollection.Count - 1) )
            {
                // Create a VariableValueViewModel object and add to collection. In binding, that create a new list item with a new TextBox
                ViewModel.AddNewRow();

                // How to set cursor and focus last row created?
            }

        }
    }

1 个答案:

答案 0 :(得分:0)

我可能误解了您的问题,但由于您将ListView绑定到VariableValueCollection,因此您对基础集合所做的任何更改都将反映在ListView中。

你应该只能从你的keydown事件处理程序中做这样的事情:

var newItem = new VariableValueViewModel();
VariableValueCollection.Add(newItem);

itemList.SelectedItem = newItem;

编辑:如何关注文本框:

以下方法允许您在可视化树中查找子控件:

/// <summary>
/// Finds the first child in the visual tree by type.
/// </summary>
public static T TryFindChild<T>(DependencyObject parent, Func<T, bool> predicate = null) where T : class {
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) {
        var child = VisualTreeHelper.GetChild(parent, i);
        if ((child is T) && (predicate!=null && predicate(child as T))) {
            return (T)((object)child);
        } else {
            T result = TryFindChild<T>(child, predicate);
            if (result != null)
                return result;
        }
    }
    return null;
}

现在你可以这样做:

itemList.ItemContainerGenerator.ContainerFromItem(newItem);
TextBox textBox = TryFindChild<TextBox>(newItem) as TextBox;
if (textBox != null) {
    textBox.Focus();
}