ListView — установить фокус на элементе управления в новой строке (UWP)

#c# #.net #listview #uwp

#c# #.net #listview #uwp

Вопрос:

У меня есть ListView поддержка an ObservableCollection . Пользователь может добавить новую строку, где в коде я добавляю новый объект в коллекцию : array.Add(obj) .

Теперь я хотел бы сделать, это сфокусироваться на a TextBox в новой строке. Проблема в том, что я считаю, что мне нужно подождать, пока не будет создан пользовательский интерфейс, и я не знаю события, которое сообщит мне, когда новая строка будет готова.

Я пытался получить новый контейнер и ссылку на TextBox in ListView_SelectionChanged , но я получал нулевые возвращаемые значения в новой строке.

Я пробовал использовать ListViewItem.Loaded , но, похоже, это не вызывается для переработанных строк.

Я также пытался ListViewItem.GotFocus , но это не было вызвано после добавления новой строки в коде.

Если бы я знал, когда элементы управления на ListViewItem были готовы, я мог бы затем найти TextBox и установить его фокус.

Возможно, я делаю это сложнее, чем нужно, но я не уверен, как поступить.

Ответ №1:

Я отвечаю на свой собственный вопрос. Ниже то, что я придумал.

Xaml: (добавьте два обработчика событий в сетку)

 <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 amp;amp; ((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 resu<
    }
    return null;
}
 

Комментарии:

1. Привет, Притхви. Я не использовал UWP более 2 лет, поэтому я действительно не знаю. Извините.