有没有办法在 WPF 中对 ComboBox 的下拉列表进行排序?

Is there a way to sort the drop-.down list of a ComboBox in WPF?

我目前正在开发一个 WPF 应用程序,该应用程序的任务是管理比萨饼店送货上门的订单。拥有一个基于 phone 数字的工作数据库至关重要。调度员在 phone 号码中写入 him/her 客户的所有详细信息(姓名、地址、评论等)。
我想要一个 ComboBox,您可以在其中键入要搜索的数字。我有点让它工作,但我错过了一个我不知道如何解决的重要部分。事情是这样的。
我想让 ComboBox 像这样工作:您开始在 ComboBox 的 .Text 字段中输入数字,在 return 将 select 最匹配的 phone 数字,并对 ObservableColletion 下拉列表中的所有其他紧密匹配的 phone 数字进行排序( 图 1)。按照标准,ComboBox 下拉列表不是 filtering/sorting 它获得的源“列表”,它只会根据您键入的内容更改 .Text 属性 中的 selection。

图1 Current state of development of the ComboBox

在匈牙利,我们有以下 phone 号码模式:
[提供商[xx]] [卡ID[xxx-xxxx]] ->9 nums
即:20 - 324-7784
(20- Telenor、70-沃达丰等...)

我有以下 XAML 组合框。

<ComboBox x:Name="PhoneBox" materialDesign:HintAssist.Hint="Keresés" IsEditable="True" 
          Style="{StaticResource MaterialDesignFloatingHintComboBox}"              
          Width="1000" Height="50" HorizontalAlignment="Left" VerticalAlignment="Center" 
          Margin="150,0,0,0" FontSize="20" 
          ItemsSource="{Binding SELECTEDPHONES, RelativeSource={RelativeSource FindAncestor,
                       AncestorType={x:Type local:Order_placeCustomerData_panel}},
                       UpdateSourceTrigger=PropertyChanged}"
          SelectedItem="{Binding SELECTED, RelativeSource={RelativeSource FindAncestor,
                        AncestorType={x:Type local:Order_placeCustomerData_panel}}}"/>

这里是 ComboBox 的当前后端。
我从头开始计算我检查过的完整 phone 数字的哪个索引,因此我可以跟踪哪个部分是新输入的部分。首先,我收集了所有满足当前条件的 phone 个数字,以及所有不满足当前条件的 phone 个数字。然后我用一个坏的交换一个好的。在此过程中,我根据他们的位置标记他们。如果一个好人的位置小于 GoodOnes.Count,它就会进入标志列表。为了完成这个过程,我将每个标记的项目与一个已经放置好的项目从顶部开始交换(好的项目的最高索引)。
这样做的原因是,当你交换 PHONES[2](坏的) 与 PHONES[5](好的)并且你有 8 个好的,在这个过程之后,PHONES[5] 将是一个带有错误数字的“洞”文件。好-好-好-好-坏-好-好-好。)

        //Propeties and stuff
        private string[] typed = new string[9];
        private int typedIndex = 0;
        private bool isReevaluating = false;
        private ObservableCollection<string> _selectedPhones;
        private string _selected;

        public ObservableCollection<string> SELECTEDPHONES
        {
            get { return _selectedPhones; }
            set 
            {
                _selectedPhones = value;
            }
        }
        public string SELECTED
        {
            get { return _selected; }
            set
            {
                _selected = value;
                OnPropertyChanged("SELECTED");
            }
        }


        //Function for Reeavluating the drop-down list
        private void ReevaluatePhones()
        {
            if (SELECTED == null)
            {
                return;
            }
            isReevaluating = true;

            typed[typedIndex] = SELECTED[typedIndex].ToString();
            string toExamine;
            List<int> Satisfies = new List<int>();
            List<int> notSatisfies = new List<int>();

            for (int j = 0; j < PHONES.Count; j++)
            {
                toExamine = PHONES[j].ToString();
                if (toExamine[typedIndex].ToString() == typed[typedIndex].ToString())
                {
                    Satisfies.Add(j);
                }
                else
                {
                    notSatisfies.Add(j);
                }
            }
            List<int> flagSatisfies = new List<int>();
            int flagLast = 0;
            for (int i = 0; i < Satisfies.Count; i++)
            {
                if (Satisfies[i] < Satisfies.Count)
                {
                    flagSatisfies.Add(Satisfies[i]);
                }

                string temp = PHONES[notSatisfies[i]];
                PHONES[notSatisfies[i]] = PHONES[Satisfies[i]];
                PHONES[Satisfies[i]] = temp;

                flagLast = notSatisfies[i];
            }

            for (int i = 0; i < flagSatisfies.Count; i++)
            {
                string temp = PHONES[flagSatisfies[i]];
                PHONES[flagSatisfies[i]] = PHONES[flagLast];
                PHONES[flagLast] = temp;
                flagLast--;
            }

            isReevaluating = false;
        }

INotifyPropertyChanged接口只是基本实现,不包含任何异常,只是ComboBox的selected [=74=时事件的调用顺序] 变化。
上面的代码工作正常,但是当您错误输入 phone 数字并从文本字段中删除一些字符时,我不会收到有关更改的通知,只有在您输入时才会收到,而不会在删除时收到。
就我在 MS 文档上读到的而言,ComboBox 在值中没有 TYPED 的可访问字段,只有 selected 值是整个 [=61] =] 号。我无法基于此进行排序,因为我没有任何基本点可以与之进行比较。

总结一下。

我想根据 ComboBox.Text 字段中输入的值对下拉列表(这是一个 ObservableColelction)进行排序。为了让我上面的解决方案起作用,我需要在 .Text 的值被部分或全部删除时得到通知。我乐于接受任何类型的指导、提示和想法。

非常感谢:)

我建议您使用 CollectionViewSource https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.collectionviewsource?view=netframework-4.8.
此 class 的实例在 window 资源中声明。

来源 属性 包含 link 到您的 collection。 属性 Filter - 代码隐藏中的过滤方法 Window.
属性 IsLiveFilteringRequestedIsLiveSortingRequested = true 用于实时过滤和排序。
LiveFilteringProperties - 添加您要过滤的属性。 在 SortDescriptions - 排序条件。
ComboBox.Text 更改时,禁用并 re-enable IsLiveFilteringRequested 进行新的过滤。

ComboBox.ItemsSource 指向在资源中创建的 CollectionViewSource 实例。