删除组合框中最后输入的字符

本文关键字:输入 字符 最后 组合 删除 | 更新日期: 2023-09-27 18:36:58

我在这里遇到了另一个问题。

我已经设置了我的组合框,以便它只接受那些与组合框项中任何项目的名称匹配的字符。

现在我在这里遇到了一个问题。请看一下我的代码,然后我会向你解释这个问题:

private void myComboBox_KeyUp(object sender, KeyEventArgs e)
    {
        // Get the textbox part of the combobox
        TextBox textBox = cbEffectOn.Template.FindName("PART_EditableTextBox", cbEffectOn) as TextBox;
        // holds the list of combobox items as strings
        List<String> items = new List<String>();
        // indicates whether the new character added should be removed
        bool shouldRemoveLastChar = true;
        for (int i = 0; i < cbEffectOn.Items.Count; i++)
        {
            items.Add(cbEffectOn.Items.GetItemAt(i).ToString());
        }
        for (int i = 0; i < items.Count; i++)
        {
            // legal character input
            if (textBox.Text != "" && items.ElementAt(i).StartsWith(textBox.Text))
            {
                shouldRemoveLastChar = false;
                break;
            }
        }
        // illegal character input
        if (textBox.Text != "" && shouldRemoveLastChar)
        {
            textBox.Text = textBox.Text.Remove(textBox.Text.Length - 1);
            textBox.CaretIndex = textBox.Text.Length;
        }
    }

在最后一个 if 条件下,我正在从组合框中删除最后一个字符。但是用户可以使用箭头键或鼠标来更改光标的位置并在文本中间输入文本。

因此,如果在文本变得无效的情况下通过在文本中间输入一个字符,我的意思是如果它与 ComboBox 中的项目不匹配,那么我应该删除最后输入的字符。任何人都可以建议我如何获取最后一个插入的字符并将其删除吗?

更新:

string OldValue = "";
private void myComboBox_KeyDown(object sender, KeyEventArgs e)
{
    TextBox textBox = cbEffectOn.Template.FindName("PART_EditableTextBox", cbEffectOn) as TextBox;
    List<String> items = new List<String>();
    for (int i = 0; i < cbEffectOn.Items.Count; i++)
    {
        items.Add(cbEffectOn.Items.GetItemAt(i).ToString());
    }
    OldValue = textBox.Text;
    bool shouldReplaceWithOldValue = true;
    string NewValue = textBox.Text.Insert(textBox.CaretIndex,e.Key.ToString()).Remove(textBox.CaretIndex + 1,textBox.Text.Length - textBox.CaretIndex);
    for (int i = 0; i < items.Count; i++)
    {
        // legal character input
        if (NewValue != "" && items.ElementAt(i).StartsWith(NewValue, StringComparison.InvariantCultureIgnoreCase))
        {
            shouldReplaceWithOldValue = false;
            break;
        }
    }
    //// illegal character input
    if (NewValue != "" && shouldReplaceWithOldValue)
    {
        e.Handled = true;
    }
}

在这里,我尝试移动KeyDown事件中的所有代码来解决上述问题。这段代码工作得很好,但有 1 个问题。

如果我有任何名为鸟类和动物的项目,那么在输入鸟类和一个空格后,我无法键入&。

我知道问题是什么,但不知道解决方案。

问题是:要打字,我必须按shift键,然后按7键。但两者都作为不同的密钥发送。

我考虑的解决方案:1)我应该将我的代码移动到KeyUp事件。但是这里会出现长按和快速打字的问题。2)我想我应该用一些东西代替e.Key。但不知道是什么。

删除组合框中最后输入的字符

我不确定这是否是你想做的,但我觉得你正在尝试做我们通常在Visual Studio Intellisense中看到的事情,在我们输入时会匹配出结果。

不应删除击键,而应使用 WPF 提供的验证机制。下面是其工作原理的示例。

涵盖的方案:

  1. 输入完全匹配组合框项目:TypedInputSelectedItem 都显示完全匹配。
  2. 输入部分匹配某些元素:TypedInput将弹出列表列入候选名单。绑定显示匹配的文本,而SelectedItem保持 null。
  3. 输入与列表中的任何项目都不匹配,无论是从开始还是在某些时候随机点:用户在视觉上得到反馈(有可能添加其他反馈信息),具有典型的红色轮廓。这 TypedInput在最后有效入境时保持有效,SelectedItem可能或可能不为 null,具体取决于最后一个 TypedInput 是否与任何项目匹配。

完整代码:

MainWindow.xaml

<Window x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:Sample"
        Title="MainWindow" Height="350" Width="525" 
        DataContext="{Binding Source={x:Static l:MainWindowViewModel.CurrentInstance}}">
    <StackPanel>
        <TextBlock>
            <Run Text="Typed valid text" />
            <Run Text="{Binding TypedText}"/>
        </TextBlock>
        <TextBlock>
            <Run Text="Valid SelectedItem" />
            <Run Text="{Binding SelectedItem}"/>
        </TextBlock>
        <ComboBox ItemsSource="{Binding FilteredItems}" IsEditable="True" IsTextSearchEnabled="False" SelectedItem="{Binding SelectedItem}">
            <ComboBox.Text>
                <Binding Path="TypedText" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <l:ContainsValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </ComboBox.Text>
        </ComboBox>
    </StackPanel>
</Window>

MainWindow.xaml.cs

namespace Sample
{
    public partial class MainWindow { public MainWindow() { InitializeComponent(); } }
}

包含验证规则.cs -- 解决方案的肉

namespace Sample
{
    using System.Globalization;
    using System.Linq;
    using System.Windows.Controls;
    public class ContainsValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            var result = MainWindowViewModel.CurrentInstance.Items.Any(x => x.ToLower(cultureInfo).Contains((value as string).ToLower(cultureInfo)));
            return new ValidationResult(result, "No Reason");
        }
    }
}

主窗口视图模型 - 支持视图模型单例

namespace Sample
{
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    public sealed class MainWindowViewModel : INotifyPropertyChanged
    {
        private string _typedText;
        private string _selectedItem;
        private static readonly MainWindowViewModel Instance = new MainWindowViewModel();
        private MainWindowViewModel()
        {
            Items = new[] { "Apples", "Apples Green", "Bananas", "Bananas & Oranges", "Oranges", "Grapes" };
        }
        public static MainWindowViewModel CurrentInstance { get { return Instance; } }
        public string SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if (value == _selectedItem) return;
                _selectedItem = value;
                OnPropertyChanged();
            }
        }
        public string TypedText
        {
            get { return _typedText; }
            set
            {
                if (value == _typedText) return;
                _typedText = value;
                OnPropertyChanged();
                OnPropertyChanged("FilteredItems");
            }
        }
        public IEnumerable<string> Items { get; private set; }
        public IEnumerable<string> FilteredItems
        {
            get
            {
                return Items == null || TypedText == null ? Items : Items.Where(x => x.ToLowerInvariant().Contains(TypedText.ToLowerInvariant()));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

与其KeyUp事件,不如在ComboBox Textbox上订阅TextChanged事件。在事件处理程序中,可以获取发生更改的偏移量。您可以在 hanlder 中使用验证逻辑,如果它使文本无效,则删除偏移处的字符。

     private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        TextBox textBox = cbEffectOn.Template.FindName("PART_EditableTextBox", cbEffectOn) as TextBox;
        textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
    }
    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        int index = e.Changes.First().Offset;
    }

您是否考虑过使用字符串变量来保存组合框文本框部分中的最后一个合法文本值?

最初,此字符串为空,因为用户尚未键入任何内容,然后在处理每个KeyUp事件时,如果输入了无效字符,则使用以前的字符串值替换文本框的文本;否则,以前的字符串值现在使用新的完整字符串更新;等待用户输入。