2016-10-14 17 views
0

ListViewにはObservableCollectionが付いています。ユーザーは新しい行を追加できます。コードでは、コレクションに新しいオブジェクトを追加します(array.Add(obj))。ListView - 新しい行(UWP)のコントロールにフォーカスを設定

私がしたいことは、新しい行のTextBoxに焦点を当てることです。問題は、UIが作成されるまで待つ必要があると信じており、新しい行が準備完了したときに通知する予定がないということです。

新しいコンテナとTextBoxへの参照をListView_SelectionChangedに取得しようとしましたが、新しい行でnull戻り値が返されました。

私はListViewItem.Loadedを使用しようとしましたが、これはリサイクルされた行には呼び出されません。

また、私はListViewItem.GotFocusを試しましたが、コード内に新しい行を追加した後では呼び出されませんでした。

ListViewItemのコントロールが準備されていることがわかったら、TextBoxが見つかり、そのフォーカスを設定できました。

多分私はこれよりも難しいと思っていますが、どうやって進めるのか分かりません。

答えて

1

私は自分自身の質問に答えています。以下は私が思いついたものです。

XAML:(グリッドに2つのイベントハンドラを追加)

<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; 
} 
関連する問題