11

MVVM で WPF DataGrid の 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 を渡します。このムービー ID は、拡張メソッドを使用して MovieList コレクションをフィルター処理するために使用されます。

4

3 に答える 3

21

監視可能なコレクションとコレクションビューの新しいインスタンスを作成しないでください。コレクションビューのフィルタープロパティに述語を割り当て、コレクションをフィルター処理するときはいつでも更新を呼び出します。

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);
    }
}
于 2012-09-26T10:27:32.323 に答える
2

DataGrid でマルチフィルタリングを有効にするために CollectionViewSource をインスタンス化する例を次に示します

CollectionViewSource は XAML ビューでインスタンス化されましたが、ビュー モデルでインスタンス化されたオブジェクトのコレクションにバインドされています。次に、ビュー モデルは CollectionViewSource を使用して、DataGrid 内のデータをフィルター処理します。

CollectionViewSource をインスタンス化するための正しいアプローチについては、議論の余地があります。

于 2012-09-28T14:10:21.917 に答える
0

これを直接実行することで、リソースの追加をスキップできDataContext = new TagViewModel();ます。通常どおりバインディングを実行します。依存性注入を使用することを強くお勧めします。

于 2012-09-26T10:17:38.527 に答える