private void HandleKeyPress(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Tab: if (SelectedItem != null) { CommitSelectionAndMoveFocus(); } break; case Key.Enter: CommitSelectionAndMoveFocus(); e.Handled = true; break; case Key.Escape: Flyout.IsOpen = false; SearchTextBox.ScrollToEnd(); SelectedItem = null; e.Handled = true; break; case Key.Down: if (Options.Items.Count > 0) { Options.ScrollIntoView(Options.Items[0]); var fe = (FrameworkElement)Options.ItemContainerGenerator.ContainerFromIndex(0); fe?.Focus(); Options.SelectedIndex = 0; e.Handled = true; } break; } }
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) { TextChange textChange = e.Changes.Last(); // We will invoke completion on text insertion and not deletion. // Also, we don't want to invoke completion on dialog load as we pre populate the target // location textbox with name of the folder when dialog is initially loaded. if (textChange.AddedLength > 0 && SearchTextBox.CaretIndex > 0) { ThreadHelper.JoinableTaskFactory.RunAsync(async() => { // grab these WPF dependant things while we're still on the UI thread int caretIndex = SearchTextBox.CaretIndex; SearchTextBoxViewModel viewModel = ViewModel; string textBeforeGetCompletion = SearchTextBox.Text; // Switch to a background thread to not block the UI thread, as this operation can take // a while for slow network connections await TaskScheduler.Default; CompletionSet completionSet = await viewModel.GetCompletionSetAsync(caretIndex); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // If the value has changed then this request is out of date. // If focus is elsewhere the work below won't be used anyway if (textBeforeGetCompletion != SearchTextBox.Text || !SearchTextBox.IsFocused) { return; } if (completionSet.Completions == null || !completionSet.Completions.Any()) { Flyout.IsOpen = false; return; } // repopulate the completion list CompletionEntries.Clear(); foreach (CompletionItem entry in completionSet.Completions) { CompletionEntries.Add(new CompletionEntry(entry, completionSet.Start, completionSet.Length)); } PositionCompletionPopup(completionSet.Length); if (CompletionEntries != null && CompletionEntries.Count > 0 && Options.SelectedIndex == -1) { CompletionItem selectionCandidate = await ViewModel.GetRecommendedSelectedCompletionAsync( completionSet: completionSet, lastSelected: SelectedItem?.CompletionItem); SelectedItem = CompletionEntries.FirstOrDefault(x => x.CompletionItem.InsertionText == selectionCandidate.InsertionText) ?? CompletionEntries[0]; Options.ScrollIntoView(SelectedItem); } Flyout.IsOpen = true; }); } }
private void Commit(CompletionEntry completion) { if (completion == null) { return; } Text = completion.CompletionItem.InsertionText; LibrarySearchBox.CaretIndex = Text.IndexOf(completion.CompletionItem.DisplayText, StringComparison.OrdinalIgnoreCase) + completion.CompletionItem.DisplayText.Length; Flyout.IsOpen = false; SelectedItem = null; }
private void Commit(CompletionEntry completion) { if (completion == null || completion.CompletionItem.InsertionText == null) { return; } ViewModel.SearchText = completion.CompletionItem.InsertionText; ViewModel.OnExternalTextChange(); SearchTextBox.CaretIndex = ViewModel.SearchText.IndexOf(completion.CompletionItem.DisplayText, StringComparison.OrdinalIgnoreCase) + completion.CompletionItem.DisplayText.Length; Flyout.IsOpen = false; SelectedItem = null; }
private void HandleListBoxKeyPress(object sender, KeyEventArgs e) { int index = SearchTextBox.CaretIndex; switch (e.Key) { case Key.Tab: case Key.Enter: CommitSelectionAndMoveFocus(); e.Handled = true; break; case Key.Up: if (Options.SelectedIndex == 0) { SelectedItem = CompletionEntries[0]; LostFocus -= OnLostFocus; SearchTextBox.Focus(); SearchTextBox.CaretIndex = index; LostFocus += OnLostFocus; } break; case Key.Escape: Flyout.IsOpen = false; SearchTextBox.ScrollToEnd(); SelectedItem = null; e.Handled = true; break; case Key.Down: case Key.PageDown: case Key.PageUp: case Key.Home: case Key.End: break; default: LostFocus -= OnLostFocus; SearchTextBox.Focus(); SearchTextBox.CaretIndex = index; LostFocus += OnLostFocus; break; } }
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) { TextChange textChange = e.Changes.Last(); // We will invoke completion on text insertion and not deletion. // Also, we don't want to invoke completion on dialog load as we pre populate the target // location textbox with name of the folder when dialog is initially loaded. if (textChange.AddedLength > 0 && SearchTextBox.CaretIndex > 0) { VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.Run(async() => { CompletionSet completionSet = await ViewModel.GetCompletionSetAsync(SearchTextBox.CaretIndex); if (completionSet.Completions == null || !completionSet.Completions.Any()) { Flyout.IsOpen = false; return; } // repopulate the completion list CompletionEntries.Clear(); foreach (CompletionItem entry in completionSet.Completions) { CompletionEntries.Add(new CompletionEntry(entry, completionSet.Start, completionSet.Length)); } PositionCompletionPopup(completionSet.Length); if (CompletionEntries != null && CompletionEntries.Count > 0 && Options.SelectedIndex == -1) { CompletionItem selectionCandidate = await ViewModel.GetRecommendedSelectedCompletionAsync( completionSet: completionSet, lastSelected: SelectedItem?.CompletionItem); SelectedItem = CompletionEntries.FirstOrDefault(x => x.CompletionItem.InsertionText == selectionCandidate.InsertionText) ?? CompletionEntries[0]; Options.ScrollIntoView(SelectedItem); } Flyout.IsOpen = true; }); } }