WPF可编辑DataGrid使用分页CollectionView [英] WPF Editable DataGrid using a Paged CollectionView
问题描述
我正在执行此帖中提出的分页数据网格)。
< Window x:Class =WpfApplication1.MainWindow
xmlns =http://schemas.microsoft .com / winfx / 2006 / xaml / presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/xaml
xmlns:vm =clr-namespace:WpfApplication1 .ViewModels
Title =MainWindowHeight =350Width =500>
< Window.DataContext>
< vm:CustomersViewModel />
< /Window.DataContext>
< Grid>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition Height =*/>
< /Grid.RowDefinitions>
& DockPanel Grid.Row =0>
< Button Content =PreviousCommand ={Binding MovePreviousCommand}Margin =2/>
< Button Content =NextCommand ={Binding MoveNextCommand}Margin =2/>
< TextBlock Grid.Row =0Margin =2VerticalAlignment =中心HorizontalAlignment =RightDockPanel.Dock =Right>
< TextBlock.Text>
< MultiBinding StringFormat =Page {0} / {1}>
< Binding Path =PageNumber/>
< Binding Path =TotalPages/>
< / MultiBinding>
< /TextBlock.Text>
< / TextBlock>
< / DockPanel>
< DataGrid ItemsSource ={Binding CustomerCollection}Grid.Row =1>
< DataGrid.Columns>
< DataGridTemplateColumn标题=活动>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< CheckBox IsChecked ={Binding Path = IsActive,UpdateSourceTrigger = PropertyChanged}/>
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< / DataGridTemplateColumn>
< DataGridTextColumn Header =First NameWidth =*Binding ={Binding FirstName}/>
< DataGridTextColumn Header =Last NameWidth =*Binding ={Binding LastName}/>
< /DataGrid.Columns>
< / DataGrid>
< / Grid>
< / Window>
版本管理似乎有一个小问题(不停止代码工作)所以您可能想在 PagedCollectionView.MoveNext
中的前四行发表评论。
public bool MoveNext()
{
// if(this._timestamp!= this._collectionView.Timestamp)
// {
// throw new InvalidOperationException(PagedCollectionViewResources。 EnumeratorVersionChanged);
//}
开关(this._position)
I am implementing a paged datagrid as proposed in this post Pagination in WPF. All works fine, but I have some checkboxes in my grid and when I try to check them, the application throws an exception because CollectionView
does not allow the editing. How can I get the list of items in the current view and convert them to a list collection? I've added the following method in the public class PagingCollectionView : CollectionView
class for testing:
private void RefreshGrid()
{
//this._currentDataGrid.DataContext = this; **throws exception** when clicking on
//this.Refresh(); **checkbox
List<Customer> list = this.Cast<Customer>().ToList(); //** still get the original list
this._currentDataGrid.DataContext = list;
this.Refresh();
//I also tried this
//this.Refresh();
//List<Customer> list = this.Cast<Customer>().ToList(); //** same result
//this._currentDataGrid.DataContext = list;
}
Ideally I would like to just get what items the view has, at this point I am setting the items per page to 5 but I am getting all 16 of them. The PagingCollectionView
works fine except that I can not check the boxes.
The PagingCollectionView
from your linked post does not implement IEditableCollectionView
, and so you are not able to change values in the grid.
Unfortunately, there does not seem to exist a standard paged collection view in WPF. But the PagedCollectionView
for Silverlight does work, it's possible to just copy that code into your project. I suppose you could also install Silverlight SDK and add a reference to System.Windows.Data.dll. Or if you can implement IEditableCollectionView
yourself, I'm sure you'd find a few takers ;).
For what looks like your best bet, you'll need all code from this page.
Test output:
ViewModel:
using System;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.Windows.Input;
namespace WpfApplication1.ViewModels
{
public class CustomersViewModel : NotifyBase // replace NotifyBase by implementing INotifyPropertyChanged
{
public PagedCollectionView CustomerCollection { get; private set; }
public int TotalPages { get { return (int)Math.Ceiling((double)CustomerCollection.ItemCount / (double)CustomerCollection.PageSize); } }
public int PageNumber { get { return CustomerCollection.PageIndex + 1; } }
public ICommand MoveNextCommand { get { return GetValue(() => MoveNextCommand); } set { SetValue(() => MoveNextCommand, value); } }
public ICommand MovePreviousCommand { get { return GetValue(() => MovePreviousCommand); } set { SetValue(() => MovePreviousCommand, value); } }
public CustomersViewModel()
{
this.CustomerCollection = new PagedCollectionView(new ObservableCollection<Customer>
{
new Customer(true, "Michael", "Delaney"),
new Customer(false, "James", "Ferguson"),
new Customer(false, "Andrew", "McDonnell"),
new Customer(true, "Sammie", "Hunnery"),
new Customer(true, "Olivia", "Tirolio"),
new Customer(false, "Fran", "Rockwell"),
new Customer(false, "Andrew", "Renard"),
});
this.CustomerCollection.PageSize = 3;
this.MoveNextCommand = new ActionCommand(MoveNext);
this.MovePreviousCommand = new ActionCommand(MovePrevious);
}
private void MoveNext()
{
this.CustomerCollection.MoveToNextPage();
OnPropertyChanged("PageNumber");
}
private void MovePrevious()
{
this.CustomerCollection.MoveToPreviousPage();
OnPropertyChanged("PageNumber");
}
}
public class Customer : NotifyBase // replace NotifyBase by implementing INotifyPropertyChanged
{
public bool IsActive { get { return GetValue(() => IsActive); } set { SetValue(() => IsActive, value); } }
public string FirstName { get { return GetValue(() => FirstName); } set { SetValue(() => FirstName, value); } }
public string LastName { get { return GetValue(() => LastName); } set { SetValue(() => LastName, value); } }
public Customer(bool isActive, string firstName, string lastName)
{
this.IsActive = isActive;
this.FirstName = firstName;
this.LastName = lastName;
}
}
public class ActionCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private Action _action;
public ActionCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter) { return true; }
public void Execute(object parameter)
{
if (_action != null)
_action();
}
}
}
Xaml (note the TemplateColumn instead of CheckBoxColumn, because of this).
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:WpfApplication1.ViewModels"
Title="MainWindow" Height="350" Width="500">
<Window.DataContext>
<vm:CustomersViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Button Content="Previous" Command="{Binding MovePreviousCommand}" Margin="2"/>
<Button Content="Next" Command="{Binding MoveNextCommand}" Margin="2"/>
<TextBlock Grid.Row="0" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Right" DockPanel.Dock="Right">
<TextBlock.Text>
<MultiBinding StringFormat="Page {0}/{1}">
<Binding Path="PageNumber" />
<Binding Path="TotalPages" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DockPanel>
<DataGrid ItemsSource="{Binding CustomerCollection}" Grid.Row="1">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Active">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsActive, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="First Name" Width="*" Binding="{Binding FirstName}"/>
<DataGridTextColumn Header="Last Name" Width="*" Binding="{Binding LastName}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
There seems to be a slight problem with version management (doesn't stop the code from working), so you might want to comment the first four lines in PagedCollectionView.MoveNext
.
public bool MoveNext()
{
//if (this._timestamp != this._collectionView.Timestamp)
//{
// throw new InvalidOperationException(PagedCollectionViewResources.EnumeratorVersionChanged);
//}
switch (this._position)
这篇关于WPF可编辑DataGrid使用分页CollectionView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!