WPF中实现类智能感知
首先要做的事情就是定义一个popup来显示我们需要展示的东西
<Popup x:Name="ConfigPopup" Height="auto" Width="150" StaysOpen="False" Placement="Bottom" IsOpen="False" HorizontalAlignment="Left"> <Grid Width="auto" Height="auto"> <ListBox x:Name="MailConfigSelection" KeyDown="MailConfigSelection_OnKeyDown" IsTextSearchEnabled="True" ItemsSource="{Binding KeysCollection}"></ListBox> </Grid> </Popup>
这里使用的是用一个Listbox来做演示,也可以使用其他的控件或者改listbox的template。popup的staysopen代表失去焦点后还显不显示。listbox绑定到一个ObservableCollection来实时改变。
后台代码
public ObservableCollection<string> KeysCollection { get; set; } = new ObservableCollection<string>(); ... private void MailConfigSelection_OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { if (e.Key == Key.Enter) { ConfigPopup.IsOpen = false; System.Windows.Controls.ListBox lb = sender as System.Windows.Controls.ListBox; if (lb == null) return; string mailConfig = lb.SelectedItem.ToString(); //Popup pp = (lb.Parent as Grid).Parent as Popup; TextBox tb = ConfigPopup.PlacementTarget as TextBox; int i = tb.CaretIndex;//获取呼出这个popup的textbox的当前光标位置 tb.Text = tb.Text.Insert(i, mailConfig) + ">";//插入选择的字符串 tb.CaretIndex = i + mailConfig.Length + 1;//移动光标 tb.Focus(); } else if (e.Key == Key.Escape) { ConfigPopup.IsOpen = false; } }
给textbox加上keyup响应事件
private void TextBox_OnKeyUp(object sender, System.Windows.Input.KeyEventArgs e) { if (e.Key != Key.OemComma) return; TextBox tbm = e.OriginalSource as TextBox; if (tbm.Text.EndsWith("<") && KeysCollection.Count != 0)//这里是这样的条件,可以根据需求来改变 { ShowPopUp(tbm.GetRectFromCharacterIndex(tbm.CaretIndex), tbm); } }
弹出popup时,我们希望popup出现在正在输入的textbox下面而且在输入的光标附近
private void ShowPopUp(Rect placementRect, TextBox tb) { ConfigPopup.PlacementTarget = tb; ConfigPopup.PlacementRectangle = placementRect; ConfigPopup.IsOpen = true; MailConfigSelection.Focus(); MailConfigSelection.SelectedIndex = 0; var listBoxItem = (ListBoxItem)MailConfigSelection.ItemContainerGenerator.ContainerFromItem(MailConfigSelection.SelectedItem); listBoxItem.Focus(); }
我们先获取到当前光标的位置Rect,tbm.GetRectFromCharacterIndex(tbm.CaretIndex)来获取rect并传给popup的PlacementRectangle,这样popup出现的位置就是我们想要的了。
在这个过程中发现弹出窗口后选择候选项时,按上下键有时候不管用,因为我们focus在popup上,上下键相应的框内所有内容的上下翻,我们希望的是在各个选项之间的切换,那么我们需要focus在里面的listitem上,通过MailConfigSelection.ItemContainerGenerator.ContainerFromItem(MailConfigSelection.SelectedItem)来获取到选中的listboxitem并把焦点给他即可。
到此,一个类智能感知就完成了,可以通过其他的各种方式来进行优化。