我有一个DataGrid,我绑定到我的视图模型中的ObservableCollection,我需要能够在DataGrid排序时对集合进行排序,以便我可以在其他地方使用这个排序顺序。我目前正在使用ObvservableCollection上的包装器来支持排序。对DataGrid进行排序时,它只对显示的数据进行排序,而不对集合中的基础数据进行排序。数据由一个整数列和一个字符串列组成,需要在两者上支持升序和降序排序。我还希望保持与标准DataGrid排序相同的用法,您可以在其中单击列标题并在升序和降序排序之间切换。我对WPF比较陌生,所以我不知道数据和命令绑定的所有细节,但我认为有一种方法可以实现我想做的事情。这是一个示例xaml来说明我的视图设置。
<DataGrid ItemsSource="{Binding mySource}"
Name="myDataGrid"
CanUserResizeRows="False"
AutoGenerateColumns="False"
HeadersVisibility="Column" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Header 1" CanUserSort="True" SortMemberPath="firstValue">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding firstValue}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Header 2" Width="*" CanUserSort="True" SortMemberPath="secondValue">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding secondValue}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
源数据的类型如下:
public class myType
{
public int firstValue { get; set; }
public string secondValue { get; set; }
// some functions and variables...
}
现在,就像我上面所说,我需要按照排序顺序访问集合中的项目,但它不需要特别是ObservableCollection。只要我可以在我访问它们的当前顺序中迭代集合中的项目,一切都很好。我想的可能是ListCollectionView或其他东西。当新项目添加到集合中时,我也不希望集合重新排序。任何新项目都应该像往常一样添加到集合的末尾。
有什么想法吗?
答案 0 :(得分:4)
DataGrid
使用基于DataSource的基础ICollectionView
,因此,如果您直接绑定ICollectionView
,则可以访问已排序的值,因为DataGrid
将直接更改排序时ICollectionView
。
小例子:
<强>代码:强>
public partial class MainWindow : Window
{
public MainWindow()
{
// dummy data source / Your ObservableCollection
var yourObservableCollection = Enumerable.Range(0, 30)
.Select(i => new MyType { FirstValue = i, SecondValue = i.ToString() });
// Create CollectionView based on the data you want to show
MySource = CollectionViewSource.GetDefaultView(yourObservableCollection);
InitializeComponent();
}
public ICollectionView MySource { get; set; }
private void Button_Click_1(object sender, RoutedEventArgs e)
{
foreach (var item in MySource.OfType<MyType>())
{
Console.WriteLine("MyType - First: {0}, Second: {1}",
item.FirstValue,
item.SecondValue);
}
}
}
public class MyType
{
public int FirstValue { get; set; }
public string SecondValue { get; set; }
}
<强>的Xaml:强>
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"`enter code here` Name="UI" Width="262" Height="318">
<Grid DataContext="{Binding ElementName=UI}">
<DataGrid Name="myDataGrid"
ItemsSource="{Binding MySource}"
CanUserSortColumns="True"
Margin="0,0,0,37" />
<Button Content="Print To Output Window"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Margin="10,0,0,10"
Width="144"
Click="Button_Click_1"/>
</Grid>
</Window>
答案 1 :(得分:3)
我知道这是一个老问题,但当我遇到类似问题时,我很难找到答案,我想按照屏幕上显示的顺序打印/导出数据。虽然@ sa_ddam213的答案是正确的,但需要进行一些调整以适应MVVM模式,所以希望这个答案对其他人有用。为了实现这一点,首先添加到{View}模型ICollectionView
(我相信这与UI使用的数据结构相同):
private ObservableCollection<yourDataType> tableData = new ObservableCollection<yourDataType>(); // The DataGridknow was originally bound to this
private ICollectionView tableDataWrapper;
然后为ICollectionView添加一个新的Getter / Setter:
public ICollectionView TableDataWrapper
{
get { return this.tableDataWrapper; }
set
{
this.tableDataWrapper = value;
OnPropertyChanged("TableDataWrapper");
}
}
在原始的TableData Setter中,每次设置表数据时都添加一行来设置包装器:
public ObservableCollection<yourDataType> TableData
{
get { return this.tableData; }
set
{
this.tableData = value;
this.TableDataWrapper = CollectionViewSource.GetDefaultView(tableData); // Add this
OnPropertyChanged("TableData");
}
}
现在更新DataGrid的绑定,使其绑定到TableDataWrapper
而不是TableData
现在按排序顺序访问数据:
this.TableDataWrapper.Cast<yourDataType>().ToList<yourDataType>()
或者如果您想将其作为ObservableCollection
:
new ObservableCollection( this.TableDataWrapper.Cast<yourDataType>().ToList<yourDataType>() )
答案 2 :(得分:1)
您可以使用ICollectionView对现有集合进行排序。它位于System.ComponentModel
下代码就像这样
var collectionView = CollectionViewSource.GetDefaultView(ObservableCollection_Name);
collectionView.SortDescriptions.Add(new SortDescription("Your Property", ListSortDirection.Descending));
在GridView或ListView中,您可以绑定现有的ObservableCollection。无需改变。
答案 3 :(得分:0)
我已经尝试过John Cummings&stuicidle的解决方案。 XAML中的DataGrid不显示任何内容。因为DataGrid的ItemsSource不是ObservableCollection。
在ViewModel中:
public ICollectionView DataGridWraper
{
get { return _dataGridWraper; }
set
{
if (_dataGridWraper != value)
{
_dataGridWraper = value;
OnPropertyChanged(nameof(DataGridWraper));
}
}
}
public ObservableCollection<Customer> Customers
{
get { return _customers; }
set
{
if (_customers != value)
{
_customers = value;
DataGridWraper = CollectionViewSource.GetDefaultView(_customer);
OnPropertyChanged(nameof(Customers));
}
}
}
在XAML中:
<DataGrid
ItemsSource="{Binding DataGridWraper, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*"/>
</DataGrid.Columns>
</DataGrid>