从CollectionViewSource C#中删除一个排序

时间:2012-01-02 04:42:21

标签: c# data-binding collectionviewsource objectdataprovider

我有一个集合视图源(CVS)实现,就像你在MSDN或许多教程中看到的那样。在我的例子中,Car类和通过对象数据提供者(ODP)在XAML中显示的Cars Collection类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));
    }

基本上我正在寻找我需要首先删除先前的二级排序,然后添加一个新的代码,因此集合视图源中始终只有两种排序。如果我然后将其扩展为允许第三,第四或任何其他级别的排序,则列表中始终只有该数量的项目。但是,由于我设置的方式,除非第一级存在,否则不存在第3级。所以不能混淆各种各样。

关于如何实现这一点的任何想法都会被贬低。

1 个答案:

答案 0 :(得分:1)

删除项目的方式不正确:您正在使用的Remove method从集合中删除指定的对象(特别是指定对象的第一个实例),但是因为您传递了一个新对象,它不会在集合中,因此不会被删除。

您最好的选择是循环收集,看看哪个项目符合您的删除条件并删除该项目。

例如:

        var sortDescriptions = lstCars.Items.SortDescriptions;

        for (int nI = sortDescriptions.Count; nI >= 0; nI--)
        {
            if (sortDescriptions[nI].PropertyName == cbxSortSecondary.SelectedItem.ToString())
            {
                sortDescriptions.RemoveAt(nI);
            }
        }

<强>更新

此行的替代方案:

                sortDescriptions.RemoveAt(nI);

是使用这一行,但它们在功能上应该是等价的:

                sortDescriptions.Remove(sortDescriptions[nI]);