我阅读了一些关于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; }
}
}
结果:
开头:
它工作正常。但是点击几下后:
无法进入事件处理程序。
答案 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; }
}