MVVMでWPFDataGridのCollectionViewSourceの小さなデモを実装しました。実装を検証し、これがCollectionViewSourceを使用するための正しいアプローチであるかどうかについてコメントするための助けを本当にいただければ幸いです。
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メソッドを呼び出し、コンマ区切りのムービーIDを渡します。これは、拡張メソッドを使用してMovieListコレクションをフィルター処理するために使用されます。
監視可能なコレクションとコレクションビューの新しいインスタンスを作成しないでください。コレクションビューのフィルタープロパティに述語を割り当て、コレクションをフィルター処理するときはいつでも更新を呼び出します。
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);
}
}
DataGridでマルチフィルタリングを有効にするためにCollectionViewSourceをインスタンス化する例を次に示します。 http://www.codeproject.com/Articles/442498/Multi-filtered-WPF-DataGrid-with-MVVM ==
CollectionViewSourceはXAMLビューでインスタンス化されましたが、ビューモデルでインスタンス化されたオブジェクトのコレクションにバインドされています。次に、ビューモデルはCollectionViewSourceを使用して、DataGridのデータをフィルタリングします。
CollectionViewSourceをインスタンス化するためのrightアプローチとは何かについては議論の余地があります。
これを直接実行してリソースの追加をスキップできます:DataContext = new TagViewModel();
そして通常どおりバインディングを実行します。ただし、依存性注入を使用することを強くお勧めします。