I have implemented small demo of CollectionViewSource for WPF DataGrid in MVVM. I would really appreciate any help to verify the implementation and comment on whether this is the right approach to use CollectionViewSource.
我在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);
}
The XAML View :
XAML视图:
<Window.Resources>
<CollectionViewSource x:Key="MovieCollection" Source="{Binding MovieList}">
</CollectionViewSource>
</Window.Resources>
<DataGrid Name="MyDG"
ItemsSource="{Binding MovieView}"
AutoGenerateColumns="True" />
The Code Behind :
守则背后:
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);
}
The Hyperlink_Click handler invokes the UpdateDataGrid method of the VM passing it comma seperated movie IDs which are then used to filter the MovieList collection using extension methods.
Hyperlink_Click处理程序调用VM的UpdateDataGrid方法,传递它的逗号分隔的电影ID,然后使用扩展方法过滤MovieList集合。
3 个解决方案
#1
17
You should not create new instances of the observable collection and the collection view. Assign a predicate to the filter property on the collecion view and call Refresh whenever you want to filter the collection.
您不应该创建可观察集合和集合视图的新实例。将谓词分配给集合视图上的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);
}
}
#2
2
Here is an example of instantiating a CollectionViewSource in order to enable multi-filtering in a DataGrid: http://www.codeproject.com/Articles/442498/Multi-filtered-WPF-DataGrid-with-MVVM
下面是一个实例化CollectionViewSource以在DataGrid中启用多重过滤的示例:http://www.codeproject.com/Articles/442498/Multi-filtered-WPFurdayGrid-with-MVVM
The CollectionViewSource was instantiated in the XAML view but is bound to a collection of objects instantiated in the view model. The view model then uses the CollectionViewSource to filter the data in the DataGrid.
CollectionViewSource在XAML视图中实例化,但绑定到视图模型中实例化的对象集合。然后,视图模型使用CollectionViewSource过滤DataGrid中的数据。
As to what is the right approach to instantiate a CollectionViewSource - that is debatable.
至于什么是实例化CollectionViewSource的正确方法 - 这是有争议的。
#3
0
You can skip adding resources by doing this directly : DataContext = new TagViewModel();
and doing your bindings normally. but I highly recommend using Dependency Injection.
您可以通过直接执行此操作来跳过添加资源:DataContext = new TagViewModel();并正常做你的绑定。但我强烈建议使用依赖注入。
#1
17
You should not create new instances of the observable collection and the collection view. Assign a predicate to the filter property on the collecion view and call Refresh whenever you want to filter the collection.
您不应该创建可观察集合和集合视图的新实例。将谓词分配给集合视图上的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);
}
}
#2
2
Here is an example of instantiating a CollectionViewSource in order to enable multi-filtering in a DataGrid: http://www.codeproject.com/Articles/442498/Multi-filtered-WPF-DataGrid-with-MVVM
下面是一个实例化CollectionViewSource以在DataGrid中启用多重过滤的示例:http://www.codeproject.com/Articles/442498/Multi-filtered-WPFurdayGrid-with-MVVM
The CollectionViewSource was instantiated in the XAML view but is bound to a collection of objects instantiated in the view model. The view model then uses the CollectionViewSource to filter the data in the DataGrid.
CollectionViewSource在XAML视图中实例化,但绑定到视图模型中实例化的对象集合。然后,视图模型使用CollectionViewSource过滤DataGrid中的数据。
As to what is the right approach to instantiate a CollectionViewSource - that is debatable.
至于什么是实例化CollectionViewSource的正确方法 - 这是有争议的。
#3
0
You can skip adding resources by doing this directly : DataContext = new TagViewModel();
and doing your bindings normally. but I highly recommend using Dependency Injection.
您可以通过直接执行此操作来跳过添加资源:DataContext = new TagViewModel();并正常做你的绑定。但我强烈建议使用依赖注入。