将ObservableCollection与MVVM中的DataGrid绑定 [英] Sort ObservableCollection bound to DataGrid in MVVM

查看:300
本文介绍了将ObservableCollection与MVVM中的DataGrid绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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 1CanUserSort =TrueSortMemberPath =firstValue>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text ={Binding firstValue}/>
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< / DataGridTemplateColumn>

< DataGridTemplateColumn Header =Header 2Width =*CanUserSort =TrueSortMemberPath =secondValue>
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< TextBlock Text ={Binding secondValue}/>
< / DataTemplate>
< /DataGridTemplateColumn.CellTemplate>
< / DataGridTemplateColumn>

< /DataGrid.Columns>
< / DataGrid>

源数据类型如下:

  public class myType 
{
public int firstValue {get;组; }
public string secondValue {get;组; }

//一些函数和变量...
}

现在,像上面所说的那样,我需要以排序的顺序访问集合中的项目,但不需要特别是一个ObservableCollection。只要我可以遍历集合中的项目,无论当前订单是什么,当我访问它们,一切都是好的。我在想可能是一个ListCollectionView或某事。当新项目添加到集合中时,我也不希望集合对其进行重新排序。任何新项目都应该被添加到通常结束的集合中。



任何想法?

解决方案

DataGrid 使用基于DataSource的基础 ICollectionView ,所以如果您直接绑定一个 ICollectionView ,您可以访问排序的值,因为 DataGrid 将直接更改



小例子:



代码: / strong>

  public partial class MainWindow:Window 
{
public MainWindow()
{
//虚拟数据源/您的ObservableCollection
var yourObservableCollection = Enumerable.Range(0,30)
.Select(i => new MyType {FirstValue = i,SecondValue = ToString()});

//根据要显示的数据创建CollectionView
MySource = CollectionViewSource.GetDefaultView(yourObservableCollection);
InitializeComponent();
}

public ICollectionView MySource {get;组;

private void Button_Click_1(object sender,RoutedEventArgs e)
{
foreach(MySource.OfType< MyType>()中的var项)
{
Console.WriteLine(MyType - First:{0},Second:{1},
item.FirstValue,
item.SecondValue);
}
}
}

public class MyType
{
public int FirstValue {get;组; }
public string SecondValue {get;组;
}

Xaml:

 < Window x:Class =WpfApplication8.MainWindow
xmlns =http://schemas.microsoft.com/winfx/2006 / xaml / presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/xaml
标题=MainWindow`在这里输入代码Name =UI宽度=262Height =318>
< Grid DataContext ={Binding ElementName = UI}>
< DataGrid Name =myDataGrid
ItemsSource ={Binding MySource}
CanUserSortColumns =True
Margin =0,0,0,37/> ;
< Button Content =打印到输出窗口
Horizo​​ntalAlignment =Left
VerticalAlignment =Bottom
Margin =10,0,0,10
宽度=144
点击=Button_Click_1/>
< / Grid>
< / Window>


I have a DataGrid that I'm binding to an ObservableCollection in my view model and I need to be able to sort the collection when the DataGrid is sorted to so I can use this sorted order elsewhere. I'm currently using a wrapper on the ObvservableCollection to support sorting. When the DataGrid is sorted it only sorts the displayed data and not the underlying data in the collection. The data consists of one integer column and one string column and needs to support ascending and descending sort on both. I also want to maintain the same usage as the standard DataGrid sort where you click a column header and it toggles between ascending and descending sort. I'm relatively new to WPF so I don't know all the ins and outs of data and command binding, but I would think there would be a way to accomplish what I want to do. Here is a sample xaml to illustrate my view set up.

<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>

The source data is of a type something like:

public class myType
{
    public int firstValue { get; set; }
    public string secondValue { get; set; }

    // some functions and variables...
}

Now, like I said above, I need access to the items in the collection in their sorted order, but it does not need to specifically be an ObservableCollection. As long as I can iterate through the items in the collection in whatever the current order is when I access them, all is good. I was thinking maybe a ListCollectionView or something. I also don't want the collection to re-sort itself when new items are added to the collection. Any new items should just be added to the end of the collection as would normally happen.

Any ideas?

解决方案

The DataGrid uses an underlying ICollectionView based on the DataSource, so if you directly bind a ICollectionView you can access the sorted values as the DataGrid will directly change the ICollectionView when sorting.

Small Example:

Code:

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>

这篇关于将ObservableCollection与MVVM中的DataGrid绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆