我的 MainWindow.xaml 中有一个绑定到List<Job>
的ComboBox控件,其中Job
是一个具有多个属性并实现INotifyPropertyChange
和IComparable
的类MainWindow类也实现了INotifyPropertyChange
。当我从数据库加载这个列表时,已正确填充绑定的ComboBox
控件。ComboBox
控件在xaml中定义为
<ComboBox x:Name="JobsComboBox" ItemsSource = "{Binding Path=AllJobs, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True"
ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="400"
MaxWidth="400" HorizontalContentAlignment="Center" />
我有一个单独的控件,允许用户按Job
的特定属性排序。当用户选择不同的排序属性时,我使用delegate
对列表排序并通知更改,如下所示:
public void SortJobsListByProperty(string? propertyName)
{
if (AllJobs != null) AllJobs.Sort(delegate(Job x, Job y)
{
int result = 0;
switch (propertyName)
{
case "Quantity":
result = x.Quantity.CompareTo(y.Quantity);
break;
case "Due Date":
result = x.DueDate.CompareTo(y.DueDate);
break;
case "Siemens PN":
result = x.Assembly.SiemensPN.CompareTo(y.Assembly.SiemensPN);
break;
case "Customer PN":
result = x.Assembly.CustomerPN.CompareTo(y.Assembly.CustomerPN);
break;
default:
result = x.JobNumber.CompareTo(y.JobNumber);
break;
}
return result;
});
NotifyPropertyChange("AllJobs");
}
奇怪的是:如果ComboBox
具有键盘焦点,我可以使用上/下箭头键在项目之间导航,并且选定的项目具有正确的排序顺序。但是,如果我单击ComboBox
上的下拉箭头,则显示的列表不具有正确的顺序。但显示的顺序与最初加载列表时的顺序相同,就好像选定项的索引遵循排序,但显示的下拉列表没有更新。
我到处寻找其他有类似问题的线程,但没有找到。我找到的最接近的解决方案是,如果集合需要排序到ComboBox
中,应该使用ObservableCollection
而不是List<Class>
。但我不知道如何排序ObservableCollection
,我觉得下拉列表中的顺序应该与箭头键导航相匹配。控件显然看到了列表的更改,或者箭头键无法按我所理解的正确顺序导航。我不熟悉数据绑定和属性更改通知,因此如果遗漏了一些明显的信息,我表示歉意。如果格式不正确或不清楚,我也表示歉意,我可以尝试澄清。提前感谢您的帮助!
编辑:我还注意到,如果我使用下拉菜单选择ListItem,当前项实际上是正确的项,只是组合框选择中的字符串不正确。例如,如果我通过箭头键或下拉菜单选择导航到ListBox中的第三项,则当前项实际上是当前排序顺序中的第三项。但其属性与ToString不匹配()方法。第三个JobNumber是123456,下拉列表中的第三个项目是123456,但根据原始排序,为该选择显示的字符串包含一些其他JobNumber,如666666。看起来ComboBox实际上做出了正确的选择,但其字符串不匹配。
3条答案
按热度按时间z5btuh9x1#
好了,在做了很多有希望的修正之后,我终于找到了有效的方法。显然,当绑定列表的排序顺序改变时,
ComboBox
项并不更新。相反,ComboBox
的底层Items
属性必须刷新。所以,在对绑定的List<Job>
进行排序之后,我简单地将**JobsComboBox.Items.Refresh()
**添加到SortJobsListByProperty(string)
方法的底部。并且一切都像它应该的那样工作。ComboBox
中的字符串被更新并与它们同步的当前项匹配。希望这对将来与这个问题搏斗的人有帮助。
hmae6n7t2#
尽管您已经找到了适合您的解决方案,但我仍然提供了实现排序的其他解释和示例。
1.如果在数据级别(ViewModel)实现排序,则需要排序的不是列表本身,而是列表的表示形式。
这种排序仅适用于“固定”列表。列表中的更改(添加/删除/替换列表项,或更改列表项的属性)仅在下次“排序刷新”时考虑。
第一个
Implementation of the BaseInpc and RelayCommand classes.
1.如果你需要动态排序,那么你需要使用Observable Collection而不是列表,并且排序应该在View中使用CollectionView来实现。
CollectionView由ItemsControl类(包括列表框、组合框)的Items属性提供。
第一个
vof42yt13#
稍微深入的回答/解释:
代码
NotifyPropertyChange("AllJobs")
正在通知所有监听器“该属性的值已更改”。但是,从技术上讲,它并没有更改。AllJobs
属性仍然拥有相同的List<Job>
示例。List<Job>
* 内部 * 的某些内容已更改(项的顺序),但它仍然是同一个对象因此数据绑定框架获取NotifyPropertyChange
调用,检查AllJobs
的值,意识到现在存在的List<Job>
与它已经拥有的List<Job>
相同,然后假设所有内容都是最新的,将其保留在那里。它假设该对象内部没有任何内容发生更改,因为没有任何内容告诉它其他情况。ObservableCollection<T>
实现了INotifyCollectionChanged
,这就是你告诉绑定系统“我的列表中的一个或多个元素已经改变,请更新它”的方式。This answer实际上包含了您所需要的大部分内容。它为您提供了
CollectionViewSource
的“正确解决方案”,但也向您展示了如何对ObservableCollection<T>
进行排序(如果您确实需要的话)(通过创建一个新的ObservableCollection<T>
并使用LINQ的OrderBy
)。