排序与数据绑定和变频器DataGrid列 [英] Sorting on datagrid column with binded data and converter

查看:173
本文介绍了排序与数据绑定和变频器DataGrid列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在DataGrid中的数据进行排序,但是当我点击已与转换器结合的列的标题,没有任何反应。我使用MVVM模式。示例如下连接。在这个例子中,网格显示柱(型),其显示的人型,因此,我使用转换器(类TypeValueConverter)。当我用这个转换器,电网不排序列类型。

 <窗​​口x:类=GridSort.MainWindow
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        的xmlns:我=CLR的命名空间:GridSort
        标题=主窗口高度=350宽度=525>
    <电网>
        <数据网格的ItemsSource ={结合人民}的AutoGenerateColumns =FALSE>
            < D​​ataGrid.Resources>
                <我:TypeValueConverter X:关键=类型转换器/>
            < /DataGrid.Resources>
            < D​​ataGrid.Columns>
                < D​​ataGridTextColumn绑定={结合姓}标题=名字/>
                < D​​ataGridTextColumn绑定={结合姓}标题=姓/>
                < D​​ataGridTextColumn绑定={结合转换器= {的StaticResource的ResourceKey =类型转换器}}标题=输入/>
            < /DataGrid.Columns>
        < /数据网格>
    < /网格>
< /窗>
 

公共类视图模型 {     私人的ICollection<人>人;     公众的ICollection<人>人     {         得到         {             如果(this.people == NULL)             {                 this.people =新的名单,其中,人物>();                 this.people.Add(新学生(){名字=查尔斯,姓=西蒙斯});                 this.people.Add(新学生(){名字=杰克,姓=男爵});                 this.people.Add(新教师(){名字=约翰,姓=禅师});                 this.people.Add(新学生(){名字=帕特丽夏,姓=菲利普斯});                 this.people.Add(新学生(){名字=马丁,姓=韦伯});             }             返回this.people;         }     } } 公共类TypeValueConverter:的IValueConverter     {         公共对象转换(对象的值,类型TARGETTYPE,对象参数,System.Globalization.CultureInfo文化)         {             如果(价值== NULL)             {                 返回DependencyProperty.UnsetValue;             }             返回value.GetType()名称。         }         公共对象ConvertBack(对象的值,类型TARGETTYPE,对象参数,System.Globalization.CultureInfo文化)         {             抛出新的NotImplementedException();         }     } 公共抽象类Person     {         公共字符串名字         {             得到;             组;         }         公共字符串姓         {             得到;             组;         }     }     公共类学生:人     {     }     公共课老师:人     {     }

解决方案

我解决了这个问题我自己:)

我创建的网格附加属性UseBindingToSort新的行为。当我将此属性设置为true,那么事件排序的网格认购。经过电网火灾事件排序我用用的IValueConverter自定义比较这是在绑定定义。 解决方法是如下:

变化对视图

 <数据网格的ItemsSource ={结合人民}的AutoGenerateColumns =FALSE我:GridSortingBehavior.UseBindingToSort =真>
 

与附加属性的新行为:

公共静态类GridSortingBehavior     {         公共静态只读的DependencyProperty UseBindingToSortProperty = DependencyProperty.RegisterAttached(UseBindingToSort的typeof(布尔)的typeof(GridSortingBehavior),新PropertyMetadata(新PropertyChangedCallback(GridSortPropertyChanged)));         公共静态无效SetUseBindingToSort(DependencyObject的元素,布尔值)         {             element.SetValue(UseBindingToSortProperty,价值);         }         私有静态无效GridSortPropertyChanged(DependencyObject的ELEM,DependencyPropertyChangedEventArgs E)         {             数据网格的网格= ELEM为DataGrid的;             如果(格!= NULL){                 如果((布尔)e.NewValue)                 {                     grid.Sorting + =新DataGridSortingEventHandler(grid_Sorting);                 }                 其他                 {                     grid.Sorting - =新DataGridSortingEventHandler(grid_Sorting);                 }             }         }         静态无效grid_Sorting(对象发件人,DataGridSortingEventArgs E)         {             DataGridTextColumn CLM = e.Column为DataGridTextColumn;             如果(CLM!= NULL)             {                 数据网格的网格=((DataGrid中)发件人);                 的IValueConverter转换器= NULL;                 如果(clm.Binding!= NULL)                 {                     约束力181 = clm.Binding为绑定;                     如果(binding.Converter!= NULL)                     {                         转换器= binding.Converter;                     }                 }                 如果(转换器!= NULL)                 {                     e.Handled =真实;                     ListSortDirection方向=(clm.SortDirection!= ListSortDirection.Ascending)? ListSortDirection.Ascending:ListSortDirection.Descending;                     clm.SortDirection =方向;                     ListCollectionView的LCV =(的ListCollectionView)CollectionViewSource.GetDefaultView(grid.ItemsSource);                     lcv.CustomSort =新ComparerWithComparer(转换器,方向);                 }             }         }

最后我自定义比较:

类ComparerWithComparer:的IComparer     {         私人System.Windows.Data.IValueConverter转换器;         私人System.ComponentModel.ListSortDirection方向;         公共ComparerWithComparer(System.Windows.Data.IValueConverter转换器,System.ComponentModel.ListSortDirection方向)         {             this.converter =转换器;             this.direction =方向;         }         公众诠释比较(对象x,对象Y)         {             反对transx = this.converter.Convert(X,typeof运算(字符串),空,System.Threading.Thread.CurrentThread.CurrentCulture);             反对transy = this.converter.Convert(Y的typeof(串),空,System.Threading.Thread.CurrentThread.CurrentCulture);             如果(方向== System.ComponentModel.ListSortDirection.Ascending){                 返回Comparer.Default.Compare(transx,transy);             }             其他             {                 返回Comparer.Default.Compare(transx,transy)*(-1);             }         }     }

而这一切。

I'm trying to sort data in datagrid, but when I click on the header of the column which has binding with the converter, nothing happens. I use MVVM pattern. Example is attached below. In the example, the grid shows column (Type) which displays type of person and therefore I use converter (class TypeValueConverter). When I use this converter, the grid doesn't sort column Type.

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

解决方案

I resolved this issue myself :)

I created new behavior for grid with attached property UseBindingToSort. When I set this property to true then event Sorting on grid is subscribed. After grid fires event sorting I use custom comparer with IValueConverter which is defined in binding. Solution is below:

Change on view

<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False"  my:GridSortingBehavior.UseBindingToSort="True">

New behavior with attached property:

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);
                }
            }
        }

And finally my custom comparer:

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);
            }
        }
    }

And that's all.

这篇关于排序与数据绑定和变频器DataGrid列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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