2012-09-26 44 views
7

Implementé una pequeña demostración de CollectionViewSource para WPF DataGrid en MVVM. Realmente agradecería cualquier ayuda para verificar la implementación y comentar si este es el enfoque correcto para usar CollectionViewSource.Implementación CollectionViewSource MVVM para WPF DataGrid

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); 
    } 

El XAML Vista:

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

el código subyacente:

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); 
    } 

El manejador Hyperlink_Click invoca el método UpdateDataGrid de la máquina virtual de pasarlo por comas separó ID de la película, que luego se utilizan para filtrar la colección MovieList usando métodos de extensión.

+0

Su código es un poco engañoso, verifique los nombres de las clases. ViewModel, TagViewModel ... para que podamos entender mejor. – HichemSeeSharp

+0

Oh, lo siento @HichemC, en realidad había cambiado el nombre de la clase al publicar la pregunta. Olvidé cambiarlo en el código detrás. Buena observación sin embargo. Gracias por llamar mi atención. – Lucifer

Respuesta

17

No debe crear nuevas instancias de la colección observable y la vista de colección. Asigne un predicado a la propiedad de filtro en la vista de colección y llame a Refresh siempre que quiera filtrar la colección.

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

Puede omitir la adición de recursos haciendo esto directamente: DataContext = new TagViewModel(); y haciendo sus enlaces normalmente. pero recomiendo usar Inyección de Dependencia.

2

Aquí es un ejemplo de instancias de un CollectionViewSource a fin de permitir multi-filtrado en una cuadrícula de datos: http://www.codeproject.com/Articles/442498/Multi-filtered-WPF-DataGrid-with-MVVM

El CollectionViewSource se crea una instancia en la vista XAML pero se une a una colección de objetos instanciado en el ver modelo. El modelo de vista luego usa CollectionViewSource para filtrar los datos en el DataGrid.

En cuanto a lo que es el derecho enfoque para crear una instancia de CollectionViewSource - eso es discutible.