我正在尝试对datagrid中的数据进行排序,但是当我点击与转换器绑定的列的标题时,没有任何反应。我使用MVVM模式。示例如下。在该示例中,网格显示列(类型),其显示人的类型,因此我使用转换器(类TypeValueConverter)。当我使用此转换器时,网格不会对列类型进行排序。
<Window x:Class="GridSort.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:GridSort"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False">
<DataGrid.Resources>
<my:TypeValueConverter x:Key="typeConverter" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding FirstName}" Header="FirstName" />
<DataGridTextColumn Binding="{Binding Surname}" Header="Surname" />
<DataGridTextColumn Binding="{Binding Converter={StaticResource ResourceKey=typeConverter}}" Header="Type" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public class ViewModel
{
private ICollection<Person> people;
public ICollection<Person> People
{
get
{
if (this.people == null)
{
this.people = new List<Person>();
this.people.Add(new Student() { FirstName = "Charles", Surname = "Simons" });
this.people.Add(new Student() { FirstName = "Jake", Surname = "Baron" });
this.people.Add(new Teacher() { FirstName = "John", Surname = "Jackson" });
this.people.Add(new Student() { FirstName = "Patricia", Surname = "Phillips" });
this.people.Add(new Student() { FirstName = "Martin", Surname = "Weber" });
}
return this.people;
}
}
}
public class TypeValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
{
return DependencyProperty.UnsetValue;
}
return value.GetType().Name;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public abstract class Person
{
public string FirstName
{
get;
set;
}
public string Surname
{
get;
set;
}
}
public class Student : Person
{
}
public class Teacher : Person
{
}
答案 0 :(得分:7)
我自己解决了这个问题:)
我使用附加属性UseBindingToSort为网格创建了新行为。当我将此属性设置为true时,将订阅事件在网格上排序。在网格触发事件排序之后,我使用自定义比较器和IValueConverter,它在绑定中定义。 解决方案如下:
更改视图
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" my:GridSortingBehavior.UseBindingToSort="True">
附加属性的新行为:
public static class GridSortingBehavior
{
public static readonly DependencyProperty UseBindingToSortProperty = DependencyProperty.RegisterAttached("UseBindingToSort", typeof(bool), typeof(GridSortingBehavior), new PropertyMetadata(new PropertyChangedCallback(GridSortPropertyChanged)));
public static void SetUseBindingToSort(DependencyObject element, bool value)
{
element.SetValue(UseBindingToSortProperty, value);
}
private static void GridSortPropertyChanged(DependencyObject elem, DependencyPropertyChangedEventArgs e)
{
DataGrid grid = elem as DataGrid;
if (grid != null){
if ((bool)e.NewValue)
{
grid.Sorting += new DataGridSortingEventHandler(grid_Sorting);
}
else
{
grid.Sorting -= new DataGridSortingEventHandler(grid_Sorting);
}
}
}
static void grid_Sorting(object sender, DataGridSortingEventArgs e)
{
DataGridTextColumn clm = e.Column as DataGridTextColumn;
if (clm != null)
{
DataGrid grid = ((DataGrid)sender);
IValueConverter converter = null;
if (clm.Binding != null)
{
Binding binding = clm.Binding as Binding;
if (binding.Converter != null)
{
converter = binding.Converter;
}
}
if (converter != null)
{
e.Handled = true;
ListSortDirection direction = (clm.SortDirection != ListSortDirection.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending;
clm.SortDirection = direction;
ListCollectionView lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(grid.ItemsSource);
lcv.CustomSort = new ComparerWithComparer(converter, direction);
}
}
}
最后我的自定义比较器:
class ComparerWithComparer : IComparer
{
private System.Windows.Data.IValueConverter converter;
private System.ComponentModel.ListSortDirection direction;
public ComparerWithComparer(System.Windows.Data.IValueConverter converter, System.ComponentModel.ListSortDirection direction)
{
this.converter = converter;
this.direction = direction;
}
public int Compare(object x, object y)
{
object transx = this.converter.Convert(x, typeof(string), null, System.Threading.Thread.CurrentThread.CurrentCulture);
object transy = this.converter.Convert(y, typeof(string), null, System.Threading.Thread.CurrentThread.CurrentCulture);
if (direction== System.ComponentModel.ListSortDirection.Ascending){
return Comparer.Default.Compare(transx, transy);
}
else
{
return Comparer.Default.Compare(transx, transy) * (-1);
}
}
}
就是这样。
答案 1 :(得分:1)
您正在使用MVVM。如果您无法将属性Type
添加到Person
类
public abstract class Person
{
public string FirstName { get; set; }
public string Surname { get; set; }
public string Type
{
get { return this.GetType().Name; }
}
}
你应该创建一个PersonViewModel
public class PersonViewModel
{
public Person Person { get; private set; }
public PersonViewModel(Person person)
{
this.Person = person;
}
public string Type
{
get { return this.Person.GetType().Name; }
}
}
调整您的People系列
private ICollection<PersonViewModel> people;
public ICollection<PersonViewModel> People
{
get
{
if (this.people == null)
{
this.people = new List<PersonViewModel>();
this.people.Add(new PersonViewModel(new Student { FirstName = "Charles", Surname = "Simons" }));
this.people.Add(new PersonViewModel(new Student { FirstName = "Jake", Surname = "Baron" }));
this.people.Add(new PersonViewModel(new Teacher { FirstName = "John", Surname = "Jackson" }));
this.people.Add(new PersonViewModel(new Student { FirstName = "Patricia", Surname = "Phillips" }));
this.people.Add(new PersonViewModel(new Student { FirstName = "Martin", Surname = "Weber" }));
}
return this.people;
}
}
并使用此XAML
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Person.FirstName}" Header="FirstName" />
<DataGridTextColumn Binding="{Binding Person.Surname}" Header="Surname" />
<DataGridTextColumn Binding="{Binding Type}" Header="Type" />
</DataGrid.Columns>
答案 2 :(得分:1)
我使用了Juptin的解决方案。但在我的情况下,我使用ConverterParameter。 所以我将它添加到他的代码中:
class ComparerWithComparer : IComparer
{
private IValueConverter converter;
private ListSortDirection direction;
private object parameter;
public ComparerWithComparer(IValueConverter converter, ListSortDirection direction, object parameter)
{
this.converter = converter;
this.direction = direction;
this.parameter = parameter;
}
public int Compare(object x, object y)
{
object transx = converter.Convert(x, typeof(string), parameter, System.Threading.Thread.CurrentThread.CurrentCulture);
object transy = converter.Convert(y, typeof(string), parameter, System.Threading.Thread.CurrentThread.CurrentCulture);
if (direction == ListSortDirection.Ascending)
{
return Comparer.Default.Compare(transx, transy);
}
return Comparer.Default.Compare(transx, transy) * (-1);
}
}
static void grid_Sorting(object sender, DataGridSortingEventArgs e)
{
DataGridTextColumn column = e.Column as DataGridTextColumn;
if (column != null)
{
DataGrid grid = ((DataGrid)sender);
IValueConverter converter = null;
object parameter = null;
if (column.Binding != null)
{
Binding binding = column.Binding as Binding;
if (binding.Converter != null)
{
converter = binding.Converter;
}
parameter = binding.ConverterParameter;
}
if (converter != null)
{
e.Handled = true;
ListSortDirection direction = (column.SortDirection != ListSortDirection.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending;
column.SortDirection = direction;
var listCollectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(grid.ItemsSource);
listCollectionView.CustomSort = new ComparerWithComparer(converter, direction,parameter);
}
}
}