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

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

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

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

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

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

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

Возможно, я делаю это сложнее, чем должно быть, но я не уверен, как действовать дальше.

c#,.net,listview,uwp,

0

Ответов: 1


1 принят

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

Xaml: (добавьте два обработчика событий в 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;
}
C # ,. сеть, ListView, UWP,
Похожие вопросы