c# - 有没有办法对 WPF 中 ComboBox 的下拉列表进行排序?
问题描述
我目前正在开发一个 WPF 应用程序,该应用程序的任务是管理送货上门披萨店的订单。拥有一个基于电话号码的工作数据库至关重要。调度员在电话号码中写下客户的所有详细信息(姓名、地址、评论等)。
我想要一个 ComboBox,您可以在其中键入要搜索的数字。我在某种程度上使它起作用,但是我错过了一个我不知道如何解决的重要部分。事情就是这样。
我希望ComboBox像这样工作:您开始在 ComboBox 的.Text字段中输入数字,作为回报,它将选择最匹配的电话号码并在下拉列表中对所有其他紧密匹配的电话号码进行排序从一个ObservableColletion(图 1)。按照标准,ComboBox 下拉列表不会过滤/排序它获得的源“列表”,它只会根据您键入的内容更改 .Text 属性中的选择。
在匈牙利,我们有以下电话号码模式:
[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 的值被部分或全部删除时得到通知。我愿意接受任何类型的指导、提示和想法。
非常感谢:)
解决方案
我建议您使用CollectionViewSource https://docs.microsoft.com/en-us/dotnet/api/system.windows.data.collectionviewsource?view=netframework-4.8。
此类的实例在窗口资源中声明。
Source属性包含指向您的集合的链接。属性过滤器- 代码隐藏窗口中的过滤方法。
属性IsLiveFilteringRequested和IsLiveSortingRequested = true用于实时过滤和排序。
在LiveFilteringProperties - 添加要过滤的属性。在SortDescriptions - 排序条件。
当ComboBox.Text更改时,禁用并重新启用IsLiveFilteringRequested以进行新过滤。
ComboBox.ItemsSource指向资源中创建的CollectionViewSource实例。
推荐阅读
- git - SVN2GIT 迁移,而 svn repo 仍在使用中
- acumatica - 使用 Acumatica 测试 SDK 时,我需要指向工具/选项屏幕以使测试 SDK 工作吗?
- php - 在 VSCode 中检查 PHP 关联数组时,某些键不显示。为什么?
- post - aiohttp Clientsession 帖子卡住了
- regex - 正则表达式只允许字符,没有重复字符的数字和长度
- sql - Firebird iSQL 输出到 csv 在记录之间留下空白行
- java - 使用 Spring Boot 在 HTTP 响应正文中发送文件和元数据
- javascript - axios获取请求,请求中的headers信息错误
- java - Java,多线程
- firebase - 无法在颤振应用程序中从 Firebase 下载 PDF