2012-09-26 37 views
7

我已经在MVVM中为WPF DataGrid实现了CollectionViewSource的小型演示。我真的很感谢任何帮助来验证实现,并评论这是否是使用CollectionViewSource的正确方法。CollectionViewSource针对WPF DataGrid的MVVM实现

public class ViewModel : NotifyProperyChangedBase 
{  
    private ObservableCollection<Movie> _movieList; 
    public ObservableCollection<Movie> MovieList 
    { 
     get { return _movieList; } 
     set 
     { 
      if (this.CheckPropertyChanged<ObservableCollection<Movie>>("MovieList", ref _movieList, ref value)) 
       this.DisplayNameChanged(); 
     } 
    } 

    private CollectionView _movieView; 
    public CollectionView MovieView 
    { 
     get { return _movieView; } 
     set 
     { 
      if (this.CheckPropertyChanged<CollectionView>("MovieView", ref _movieView, ref value)) 
       this.DisplayNameChanged(); 
     } 
    } 

    public ViewModel() 
    { 
      MovieView = GetMovieCollectionView(MovieList); 
    } 

    private void DisplayNameChanged() 
    { 
     this.FirePropertyChanged("DisplayName"); 
    } 

    public void UpdateDataGrid(string uri) 
    {    
     MovieView = GetMovieCollectionView(new ObservableCollection<Movie>(MovieList.Where(mov => uri.Contains(mov.ID.ToString())).ToList<Movie>())); 
    } 

    public CollectionView GetMovieCollectionView(ObservableCollection<Movie> movList) 
    { 
     return (CollectionView)CollectionViewSource.GetDefaultView(movList); 
    } 

的XAML检视:

<Window.Resources> 
    <CollectionViewSource x:Key="MovieCollection" Source="{Binding MovieList}"> 
    </CollectionViewSource> 
    </Window.Resources> 
    <DataGrid Name="MyDG" 
      ItemsSource="{Binding MovieView}" 
      AutoGenerateColumns="True" /> 

后面的代码:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Resources.Add("TagVM", new TagViewModel()); 
     this.DataContext = this.Resources["TagVM"]; 
    } 

    private void Hyperlink_Click(object sender, RoutedEventArgs e) 
    { 
     string uri = ((Hyperlink)sender).NavigateUri.ToString(); 
     ((ViewModel)this.DataContext).UpdateDataGrid(uri); 
    } 

的Hyperlink_Click处理程序调用VM的UpdateDataGrid方法传递逗号分隔电影标识,其然后被用于使用扩展方法过滤MovieList集合。

+0

您的代码有点误导,请验证类名。 ViewModel,TagViewModel ..所以我们可以更好地理解。 – HichemSeeSharp

+0

对不起@HichemC,实际上在发布问题时已经重命名了类名。忘记在后面的代码中改变它。虽然好的观察。感谢您的关注。 – Lucifer

回答

17

您不应创建可观察集合和集合视图的新实例。将谓词分配给collecion视图上的filter属性,并在需要过滤集合时调用Refresh。

public class ViewModel : NotifyProperyChangedBase 
{  
    string uri; 

    public ObservableCollection<Movie> MovieList { get; private set; } 

    public CollectionView MovieView { get; private set; } 

    public ViewModel(MoveList movieList) 
    { 
     MovieList = movieList; 
     MovieView = GetMovieCollectionView(MovieList); 
     MovieView.Filter = OnFilterMovie; 
    } 

    public void UpdateDataGrid(string uri) 
    {  
     this.uri = uri; 
     MovieView.Refresh(); 
    } 

    bool OnFilterMovie(object item) 
    { 
     var movie = (Movie)item; 
     return uri.Contains(movie.ID.ToString()); 
    } 

    public CollectionView GetMovieCollectionView(ObservableCollection<Movie> movList) 
    { 
     return (CollectionView)CollectionViewSource.GetDefaultView(movList); 
    } 
} 
0

您可以直接跳过添加资源:DataContext = new TagViewModel();并正常进行绑定。但我强烈建议使用依赖注入。

2

这里是为了使在数据网格多滤波实例化一个CollectionViewSource的一个示例:http://www.codeproject.com/Articles/442498/Multi-filtered-WPF-DataGrid-with-MVVM

的CollectionViewSource被实例化在XAML视图但势必会在被实例化的对象的集合查看模型。视图模型然后使用CollectionViewSource来过滤DataGrid中的数据。

至于什么是正确的方法来实例化一个CollectionViewSource - 这是有争议的。