ListView-将焦点放在新行(UWP)中的控件上 [英] ListView - Set focus on a control in a new row (UWP)

查看:68
本文介绍了ListView-将焦点放在新行(UWP)中的控件上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由ObservableCollection支持的ListView.用户可以添加一个新行,在代码中,我可以在集合中添加一个新对象:array.Add(obj).

I have a ListView backed by an ObservableCollection. The user can add a new row, where in code I add a new object to the collection: array.Add(obj).

现在我想做的是将焦点放在新行中的TextBox上.问题在于,我认为我需要等到创建UI之后,而且我不知道有什么事件会让我知道新行何时准备就绪.

Now what I'd like to do is give focus to a TextBox in the new row. The problem is that I believe I need to wait until the UI is created, and I don't know of an event that will let me know when the new row is ready.

我尝试获取新容器和ListView_SelectionChanged中对TextBox的引用,但是我在新行中获取了空返回值.

I've tried getting the new container and a reference to TextBox in ListView_SelectionChanged, but I was getting null return values on the new row.

我已经尝试过使用ListViewItem.Loaded,但这似乎并没有被称为回收行.

I've tried using ListViewItem.Loaded, but this doesn't seem to be called for recycled rows.

我也尝试过ListViewItem.GotFocus,但是在代码中添加了新行之后并没有调用它.

I also tried ListViewItem.GotFocus, but this wasn't called after adding a new row in code.

如果我知道ListViewItem上的控件何时准备就绪,则可以找到TextBox并设置其焦点.

If I knew when the controls on the ListViewItem were ready, I could then find the TextBox and set its focus.

也许我正在使这一过程变得比它所需要的难,但是我不确定如何进行.

Maybe I'm making this harder than it needs to be, but I'm not sure how to proceed.

推荐答案

我正在回答自己的问题.以下是我的想法.

I'm answering my own question. Below is what I came up with.

Xaml :(向网格添加两个事件处理程序)

Xaml: (add two event handlers to Grid)

<DataTemplate x:Key="MyTemplate" x:DataType="model:Card">
    <Grid GotFocus="ListViewGrid_GotFocus" DataContextChanged="ListViewGrid_DataContextChanged">
        <StackPanel Orientation="Horizontal">
            <TextBox Name="Text1" Text="{x:Bind Text1}" />
        </StackPanel>
    </Grid>
</DataTemplate>

代码:

MyListView.Items.VectorChanged += ListViewItems_VectorChanged; // in constructor

private void AddRow_Click(object sender, RoutedEventArgs e) {

    card = ....
    _newRowCard = card;
    _array.Add(card);
}

private void ListViewItems_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event) {

    // If new row added, at this point we can safely select and scroll to new item
    if (_newRowCard != null) {
        MyListView.SelectedIndex = MyListView.Items.Count - 1; // select row
        MyListView.ScrollIntoView(MyListView.Items[MyListView.Items.Count - 1]);   // scroll to bottom; this will make sure new row is visible and that DataContextChanged is called
    }
}

private void ListViewGrid_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args) {

    // If new row added, at this point the UI is created and we can set focus to text box 
    if (_newRowCard != null) {
        Grid grid = (Grid)sender;
        Card card = (Card)grid.DataContext;  // might be null
        if (card == _newRowCard) {
            TextBox textBox = FindControl<TextBox>(grid, typeof(TextBox), "Text1");
            if (textBox != null) textBox.Focus(FocusState.Programmatic);
            _newRowCard = null;
        }
    }
}

private void ListViewGrid_GotFocus(object sender, RoutedEventArgs e) {
    // If user clicks on a control in the row, select entire row
    MyListView.SelectedItem = (sender as Grid).DataContext;
}

public static T FindControl<T>(UIElement parent, Type targetType, string ControlName) where T : FrameworkElement {

    if (parent == null) return null;
    if (parent.GetType() == targetType && ((T)parent).Name == ControlName) return (T)parent;

    int count = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < count; i++) {
        UIElement child = (UIElement)VisualTreeHelper.GetChild(parent, i);
        T result = FindControl<T>(child, targetType, ControlName);
        if (result != null) return result;
    }
    return null;
}

这篇关于ListView-将焦点放在新行(UWP)中的控件上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆