从 CollectionViewSource C# 中删除排序
我有一个 Collection View Source (CVS),其实现方式与您在 MSDN 或许多教程中看到的非常相似。在我的例子中,有一个 Car 类和一个 Cars Collection 类,该类通过对象数据提供程序 (ODP) 在 XAML 中显示,CVS 链接到此。一切都运转良好。
我添加了一个排序,然后最终达到了允许用户选择 Car 类的属性进行排序的阶段。
接下来我想添加二次排序。我的问题不是添加排序,而是删除它。我的问题是这样的。在我的代码中,除非首先存在主要排序,否则不会发生辅助排序(辅助控制被禁用)。可以说是这样,现在如果我进行二次排序,它会起作用,但如果我选择另一个属性进行排序,则什么也不会发生。这是因为添加了第三种排序,如果我选择另一个属性,则不会发生任何事情(添加第四种排序,依此类推)。
在添加下一个辅助排序之前,我无法在任何地方找到允许我删除最后应用的辅助排序的语法。
鉴于只有两个项目 - 主要排序 [0] 和辅助排序 [1],我应该能够使用如下代码:
lstCars.Items.SortDescriptions.RemoveAt(1);
但这不起作用,甚至清空了我的选择项组合框(不是我的实际问题)。
我正在尝试这样的事情:
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
从我知道存在的源中删除一个实际的项目,因为它是从辅助组合框中选择时放置在那里的。但是,虽然这应该有效,但由于某种原因却没有。
下面是我的一些代码:
private void cbxSortPrimary_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//MessageBox.Show(((ComboBox)sender).Name);
//Code to check if sorting is required or not, if so then do it.
if(cbxSortPrimary.SelectedIndex == 0)//Sort Off
{
txtPrimary.Foreground = Brushes.Green;
lstCars.Items.SortDescriptions.Clear();
cbxSortSecondary.IsEnabled = false;
chkSortSecAsc.IsEnabled = false;
}
else//Sort On
{
txtPrimary.Foreground = Brushes.Red;
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
cbxSortSecondary.IsEnabled = true;
chkSortSecAsc.IsEnabled = true;
}
}
private void cbxSortSecondary_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//If there is no primary sort just exit the method.
if(cbxSortPrimary.SelectedIndex == 0) return;
if(cbxSortSecondary.SelectedIndex == 0)//Sort Off
{
txtSecondary.Foreground = Brushes.Green;
RemoveSecondarySort((bool)chkSortSecAsc.IsChecked);
}
else//Sort On
{
txtSecondary.Foreground = Brushes.Red;
ApplySecondarySort((bool)chkSortSecAsc.IsChecked);
}
}
private void chkSortPriAsc_Checked(object sender, RoutedEventArgs e)
{
//Check to see if list is null, if so then exit (nothing to sort).
if(lstCars == null) return;
if(cbxSortPrimary.SelectedIndex > 0)
{
if(chkSortPriAsc.IsChecked == true) //Sort Ascending
{
chkSortPriAsc.Foreground = Brushes.Green;
chkSortPriAsc.Content = "Asc";
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
}
else //Sort Decending
{
chkSortPriAsc.Foreground = Brushes.Red;
chkSortPriAsc.Content = "Dec";
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
}
}
}
private void chkSortSecAsc_Checked(object sender, RoutedEventArgs e)
{
//Check to see if list is null, if so then exit (nothing to sort).
if(lstCars == null) return;
//If there is no primary sort just quit.
if(cbxSortPrimary.SelectedIndex == 0) return;
if(cbxSortSecondary.SelectedIndex > 0)
{
if(chkSortSecAsc.IsChecked == true) //Sort Ascending
{
chkSortSecAsc.Foreground = Brushes.Green;
chkSortSecAsc.Content = "Asc";
ApplySecondarySort((bool)chkSortPriAsc.IsChecked);
}
else //Sort Decending
{
chkSortSecAsc.Foreground = Brushes.Red;
chkSortSecAsc.Content = "Dec";
ApplySecondarySort((bool)chkSortPriAsc.IsChecked);
}
}
}
private void ApplyPrimarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
//Finally get the property to be sorted on and apply the sort, else remove any existing sorts.
lstCars.Items.SortDescriptions.Clear();
lstCars.Items.SortDescriptions.Add(new SortDescription(cbxSortPrimary.SelectedItem.ToString(), direction));
//Then refresh the view.
CollectionViewSource.GetDefaultView(lstCars.ItemsSource).Refresh();
}
private void ApplySecondarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
lstCars.Items.SortDescriptions.Add(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
//Then refresh the view.
CollectionViewSource.GetDefaultView(lstCars.ItemsSource).Refresh();
}
private void RemoveSecondarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
}
本质上,我正在寻找需要首先删除以前的辅助排序的代码,然后添加一个新的排序,因此集合视图源中始终只有两种排序。如果我随后将其扩展为允许第三、第四或任何其他级别的排序,则列表中始终只有该数量的项目。然而,由于我的设置方式,除非首先存在第二级,否则第三级不能存在。所以不可能有任何混淆。
任何有关如何实现这一点的想法将不胜感激。
I have a Collection View Source (CVS) implemented much like you see in MSDN or many tutorials. In my case, a Car class, and a Cars Collection class which is shown in XAML via an Object Data Provider (ODP) The CVS is linked to this. It all works well.
I added a sort, then eventually got it to a stage where I could allow the user to select the property of the Car class to sort on.
Next I want to add a secondary sort. My problem is not adding the sort, but removing it. My problem is this. In my code, no secondary sort and happen (secondary control is disabled) unless a primary sort exists first. Lets say it does, now if I do a secondary sort, it works, but if I select another property to sort on, nothing happens. This is because a third sort is added, if I select another property, nothing happens (a fourth sort is added and so on).
I cant find the syntax anywhere that will let me remove the secondary sort applied last, before adding the next secondary sort.
Given there are only ever two items - Primary sort [0] and Secondary sort [1], I should be able to use code like:
lstCars.Items.SortDescriptions.RemoveAt(1);
but this doesnt work and even empties my combo boxes of selection items (not my actual question).
I am trying something like this:
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
To remove an actual Item from the source that I know exists because it was put there when selected from the secondary combobox. But while this should be working, it for some reason is not.
Below is some of my code:
private void cbxSortPrimary_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//MessageBox.Show(((ComboBox)sender).Name);
//Code to check if sorting is required or not, if so then do it.
if(cbxSortPrimary.SelectedIndex == 0)//Sort Off
{
txtPrimary.Foreground = Brushes.Green;
lstCars.Items.SortDescriptions.Clear();
cbxSortSecondary.IsEnabled = false;
chkSortSecAsc.IsEnabled = false;
}
else//Sort On
{
txtPrimary.Foreground = Brushes.Red;
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
cbxSortSecondary.IsEnabled = true;
chkSortSecAsc.IsEnabled = true;
}
}
private void cbxSortSecondary_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//If there is no primary sort just exit the method.
if(cbxSortPrimary.SelectedIndex == 0) return;
if(cbxSortSecondary.SelectedIndex == 0)//Sort Off
{
txtSecondary.Foreground = Brushes.Green;
RemoveSecondarySort((bool)chkSortSecAsc.IsChecked);
}
else//Sort On
{
txtSecondary.Foreground = Brushes.Red;
ApplySecondarySort((bool)chkSortSecAsc.IsChecked);
}
}
private void chkSortPriAsc_Checked(object sender, RoutedEventArgs e)
{
//Check to see if list is null, if so then exit (nothing to sort).
if(lstCars == null) return;
if(cbxSortPrimary.SelectedIndex > 0)
{
if(chkSortPriAsc.IsChecked == true) //Sort Ascending
{
chkSortPriAsc.Foreground = Brushes.Green;
chkSortPriAsc.Content = "Asc";
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
}
else //Sort Decending
{
chkSortPriAsc.Foreground = Brushes.Red;
chkSortPriAsc.Content = "Dec";
ApplyPrimarySort((bool)chkSortPriAsc.IsChecked);
}
}
}
private void chkSortSecAsc_Checked(object sender, RoutedEventArgs e)
{
//Check to see if list is null, if so then exit (nothing to sort).
if(lstCars == null) return;
//If there is no primary sort just quit.
if(cbxSortPrimary.SelectedIndex == 0) return;
if(cbxSortSecondary.SelectedIndex > 0)
{
if(chkSortSecAsc.IsChecked == true) //Sort Ascending
{
chkSortSecAsc.Foreground = Brushes.Green;
chkSortSecAsc.Content = "Asc";
ApplySecondarySort((bool)chkSortPriAsc.IsChecked);
}
else //Sort Decending
{
chkSortSecAsc.Foreground = Brushes.Red;
chkSortSecAsc.Content = "Dec";
ApplySecondarySort((bool)chkSortPriAsc.IsChecked);
}
}
}
private void ApplyPrimarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
//Finally get the property to be sorted on and apply the sort, else remove any existing sorts.
lstCars.Items.SortDescriptions.Clear();
lstCars.Items.SortDescriptions.Add(new SortDescription(cbxSortPrimary.SelectedItem.ToString(), direction));
//Then refresh the view.
CollectionViewSource.GetDefaultView(lstCars.ItemsSource).Refresh();
}
private void ApplySecondarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
lstCars.Items.SortDescriptions.Add(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
//Then refresh the view.
CollectionViewSource.GetDefaultView(lstCars.ItemsSource).Refresh();
}
private void RemoveSecondarySort(bool asc)
{
ListSortDirection direction = new ListSortDirection();
//Next determine if the direction of the sort is Ascending or Decending.
if(asc)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
lstCars.Items.SortDescriptions.Remove(new SortDescription(cbxSortSecondary.SelectedItem.ToString(), direction));
}
Esentially I am looking for the code I need to first remove the previous secondary sort, then add a new one so there is always only two sorts in the collection view source. If I were to then expand this to allow a third, fourth or whatever other level of sorting there would always only be that number of items in the list. However, because of the way I have it set up, a 3rd level cant exist unless a second level exists first. So there can be no mix up of sorts.
Any ideas on how to implement this would be appreicated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您删除项目的方式不正确:您使用的删除方法 are using 从集合中删除指定的对象(具体来说,指定对象的第一个实例),但由于您传递的是新对象,因此它不会在集合中,因此不会被删除。
最好的办法是循环浏览集合,看看哪个项目符合您的删除标准,然后删除该项目。
例如:
更新
此行的替代方法:
是使用此行,但它们在功能上应该是等效的:
The way you are removing the items is incorrect: the Remove method that you are using removes the specified object from the collection (specifically, the first instance of the specified object), but since you are passing a new object, it won't be in the collection and thus won't be removed.
Your best bet is to cycle through the collection and see which item meets your criteria for removal and remove that item.
For example:
Update
The alternative to this line:
is to use this line, but they should be functionally equivalent: