首页 > 解决方案 > 有没有办法对 WPF 中 ComboBox 的下拉列表进行排序?

问题描述

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

图1 ComboBox的发展现状

在匈牙利,我们有以下电话号码模式:
[provider[xx]] [card ID[xxx-xxxx]] ->9 nums
Ie : 20 - 324-7784
(20- Telenor, 70 - Vodafone, etc...)

我有 ComboBox 的以下 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 的当前后端。
我从头开始数我检查过的完整电话号码的索引,所以我可以跟踪哪个部分是新键入的部分。首先我收集所有满足当前条件的电话号码,以及所有不满足的电话号码。然后我用一个坏的交换每一个好的。在此过程中,我根据他们的位置标记他们。如果一个好人的位置小于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 属性发生变化时事件的调用顺序。
上面的代码可以正常工作,但是当您错误输入电话号码并从文本字段中删除一些字符时,我不会收到有关更改的通知,只有在您输入时才会收到通知,从不会在删除时收到通知。
据我在 MS docs 上阅读,ComboBox 没有可访问的字段用于TYPED值,仅适用于选定的值,即整个电话号码。我无法基于此进行排序,因为我没有任何基本点可以与之进行比较。

总结一下。

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

非常感谢:)

标签: c#wpfsortingcomboboxinotifypropertychanged

解决方案


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

Source属性包含指向您的集合的链接。属性过滤器- 代码隐藏窗口中的过滤方法。
属性IsLiveFilteringRequestedIsLiveSortingRequested = true用于实时过滤和排序。
LiveFilteringProperties - 添加要过滤的属性。在SortDescriptions - 排序条件。
ComboBox.Text更改时,禁用并重新启用IsLiveFilteringRequested以进行新过滤。

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


推荐阅读