CollectionViewSource过滤后的DataGrid在几次单击后停止运行

时间:2014-12-02 17:41:07

标签: c# wpf datagrid

我阅读了一些关于DataGrid使用CollectionViewSource自动过滤的文章,然后我使用了它,但我发现它会在点击几下后停止工作。如果有人能让我知道出了什么问题,我会很高兴。

在.net 4.5中工作。

以下是一个可以重现问题的小型演示:

XAML:

<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="dg" Margin="0,32,0,0"/>
        <ComboBox x:Name="combo" VerticalAlignment="Top" Margin="0,5,80,0" SelectionChanged="combo_SelectionChanged"/>
        <Button Content="Button" Margin="0,7,0,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="75" Click="Button_Click"/>

    </Grid>
</Window>

C#:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        void cvs_Filter(object sender, FilterEventArgs e)
        {
            if ((e.Item as Wrap) == null || combo.SelectedItem == null) return;
            if ((e.Item as Wrap).Int == (int)combo.SelectedItem)
                e.Accepted = true;
            else
                e.Accepted = false;
        }

        private void combo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            (dg.ItemsSource as ICollectionView).Refresh();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var oc = new ObservableCollection<Wrap>(from i in new[] { 1, 2, 3, 4, 1, 5, 3, 6, 7, 8, 9, 2, 3, 6, 7, 8, 4, 3, 7, 9, 8, 4, 4, 3, 2, 2 }
                                                    select new Wrap { Int = i });
            combo.ItemsSource = Enumerable.Range(1, 9);
            var cvs = new CollectionViewSource();
            cvs.Source = oc;
            cvs.Filter += cvs_Filter;
            dg.ItemsSource = cvs.View;
            combo.SelectedIndex = 0;
        }
    }

    class Wrap
    {
        public int Int { get; set; }
    }
}

结果:

开头:

enter image description here

它工作正常。但是点击几下后:

enter image description here

无法进入事件处理程序。

2 个答案:

答案 0 :(得分:1)

cvs收集垃圾。

所以解决方案是保留对它的任何引用。

答案 1 :(得分:0)

我也不确定为什么你的原始代码不起作用,但你可以对你的过滤器进行更多声明。下面的代码确实有用(XAML没有改变):

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void combo_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        (dg.ItemsSource as ICollectionView).Refresh();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var oc = new ObservableCollection<Wrap>(from i in new[] { 1, 2, 3, 4, 1, 5, 3, 6, 7, 8, 9, 2, 3, 6, 7, 8, 4, 3, 7, 9, 8, 4, 4, 3, 2, 2 }
                                                select new Wrap { Int = i });
        combo.ItemsSource = Enumerable.Range(1, 9);
        var cvs = new CollectionViewSource();
        cvs.Source = oc;
        cvs.View.Filter = o =>
            {
                if ((o as Wrap) == null || combo.SelectedItem == null) 
                    return false;
                return (o as Wrap).Int == ((int)(combo.SelectedItem));
            };
        dg.ItemsSource = cvs.View;
        combo.SelectedIndex = 0;
    }
}

class Wrap
{
    public int Int { get; set; }
}