2014-12-02 56 views
-1

我閱讀了一些關於自動過濾DataGrid的文章,使用CollectionViewSource,然後我使用它,但是我發現它會在點擊幾下後停止工作。如果有人能讓我知道哪裏出了問題,我會很高興。CollectionViewSource過濾後的DataGrid在幾次點擊後停止運作

在.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

無法進入事件處理程序。

+0

我不能說爲什麼這不起作用 - 但我會說,如果你開始使用WPF,使用MVVM模式是絕對必須的。做一些事情,比如在你的控制代碼背後創建你的源代碼集合,很快就會變得站不住腳。 – Andrew 2014-12-02 17:58:17

+0

@Andrew它只是一個快速演示。在我的真實項目中,它帶有動態數據,而且我的wpf不太好,所以我對代碼隱藏感到更加舒適。 – HuStmpHrrr 2014-12-02 18:04:15

+0

我希望downvote可以提供一個理由。 – HuStmpHrrr 2014-12-02 21:00:06

回答

0

cvs獲取垃圾收集。

所以解決辦法是保留任何參考。

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; } 
} 
相關問題