2013-08-27 160 views
3

我有一個DataGrid,我綁定到我的視圖模型中的ObservableCollection,我需要能夠對DataGrid進行排序時對集合進行排序,以便我可以在其他地方使用此排序順序。我目前在ObvservableCollection上使用包裝來支持排序。 DataGrid排序時,它只對顯示的數據進行排序,而不排序集合中的基礎數據。數據由一個整數列和一個字符串列組成,需要支持升序和降序排序。我還希望保持與標準DataGrid排序相同的用法,即單擊列標題並在升序和降序之間切換。我對WPF比較陌生,所以我不知道數據和命令綁定的所有細節,但我認爲會有辦法完成我想要做的事情。這裏是一個示例xaml來說明我的視圖設置。排序ObservableCollection綁定到MVVM中的DataGrid

<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什麼的。我也不希望集合在新項目添加到集合時重新排序。任何新項目都應該像正常情況一樣添加到集合的末尾。

任何想法?

回答

3

DataGrid使用基於數據源的底層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> 
+0

我不得不修改這一點在我的MVVM的設置工作,但我得到它的工作。感謝ICollectionView的提示。 – climbak

0

您可以使用ICollectionView梳理現有的集合。據System.ComponentModel

下找到

的代碼是這樣

var collectionView = CollectionViewSource.GetDefaultView(ObservableCollection_Name); 
     collectionView.SortDescriptions.Add(new SortDescription("Your Property", ListSortDirection.Descending)); 

在你的GridView或ListView可以綁定在現有的ObservableCollection。無需更改。

0

我知道這是一個古老的問題,但當我遇到類似的問題時,我想努力找到答案,我想按照它在屏幕上顯示的順序打印/導出數據。雖然@ sa_ddam213的答案是正確的,但它需要一些適合MVVM模式的調整,所以希望這對其他人有用。要做到這一點首先添加到您的視圖模型的ICollectionView(我相信這是由UI使用的相同數據結構):

private ObservableCollection<yourDataType> tableData = new ObservableCollection<yourDataType>(); // The DataGridknow was originally bound to this 
private ICollectionView tableDataWrapper; 

然後添加一個新的getter/setter您ICollectionView:

public ICollectionView TableDataWrapper 
{ 
    get { return this.tableDataWrapper; } 
    set 
    { 
     this.tableDataWrapper = value; 
     OnPropertyChanged("tableDataWrapper"); 
    } 
} 

而且在原始資料表二傳手添加一行到每個表中的數據集時設置包裝:

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>()) 
相關問題