question

ComptonAlvaro avatar image
0 Votes"
ComptonAlvaro asked ComptonAlvaro commented

How to order by a column which value is set in a converter?



I have a datagrid which one column is set with a value converter. This is the code:

DataGridColumn:

 <DataGridCheckBoxColumn Header="My Column" Binding="{Binding ., Converter={StaticResource MyConverter}}"/>

My Converter:

 object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
             //The code of the converter
         }//converter




     object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
     {
         throw new NotImplementedException();
     }

The converter return a bool, so I would like to can order the rows, first which rows which colum is true or at contrary, first the rows which column has a false value.

But it does not allow to order by this column.

I am using MVVM pattern, so if it possible, I would like to use a solution that respect this.

How could I order the rows by this column?



Thanks.


windows-wpf
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

for Sort/Order, filter and Group you should use ICollectionView's LiveSorting instead of IValueConverter.

0 Votes 0 ·
DaisyTian-1203 avatar image
1 Vote"
DaisyTian-1203 answered ComptonAlvaro commented

I made a simple example, which is whether the member is older than 18 years old or not.
The XAML code is:

 <Window.Resources>
         <local:AgeToRangeConver x:Key="MyConverter"></local:AgeToRangeConver>
         <Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
             <Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="{x:Type GroupItem}">
                         <Expander IsExpanded="True">
                             <Expander.Header>
                                 <TextBlock Text="{Binding Path=Name}"/>
                             </Expander.Header>
                             <ItemsPresenter />
                         </Expander>
                     </ControlTemplate>
                 </Setter.Value>
             </Setter>
         </Style>
     </Window.Resources>
     <Grid>
         <DataGrid x:Name="dataGrid" ItemsSource="{Binding }" AutoGenerateColumns="False"  SelectionMode="Extended" SelectionUnit="CellOrRowHeader" >
             <DataGrid.GroupStyle>
                 <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
                     <GroupStyle.Panel>
                         <ItemsPanelTemplate>
                             <DataGridRowsPresenter/>
                         </ItemsPanelTemplate>
                     </GroupStyle.Panel>
                 </GroupStyle>
             </DataGrid.GroupStyle>
             <DataGrid.Columns>
                 <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name}"/>
                 <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age}" />
                 <DataGridTextColumn Header="Adult ?" Width="100"  Binding="{Binding Age,Converter={StaticResource MyConverter},ConverterParameter=bool}"/>
                 <DataGridTextColumn Header="Address" Width="150"  Binding="{Binding Address}"/>
                   
             </DataGrid.Columns>
         </DataGrid>
     </Grid>

C# code is:

     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
             ObservableCollection<Member> memberData = new ObservableCollection<Member>();
             Random radom = new Random();
    
             for (int i = 1; i < 20; i++)
             {
                 Member men = new Member();
                 men.Age = radom.Next(40);
                 men.Name = "JOE" + i.ToString();
                 men.Address = "Rount AA, Number" + i.ToString();
                 memberData.Add(men);
             }
             dataGrid.ItemsSource = memberData;
             ICollectionView view = CollectionViewSource.GetDefaultView(memberData);
             view.GroupDescriptions.Add(new PropertyGroupDescription("Age", new AgeToRangeConver()));
    
         }
     }
     class AgeToRangeConver : IValueConverter
     {
         public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
         {
             if (parameter.ToString() == "bool")
             {
                 int iValue = (int)value;
                 if (0 <= iValue && iValue < 18)
                 {
                     return false;
                 }
                 else
                 {
                     return true;
                 }
                   
             }
             else
             {
                 int iValue = (int)value;
                 if (0 <= iValue && iValue < 18)
                 {
                     return "Child";
                 }
                 else
                 {
                     return "Adult";
                 }
             }
         }
    
         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
         {
             throw new NotImplementedException();
         }
    
     }
    
     public class Member
     {
         public string Name { get; set; }
         public int Age { get; set; }
    
         public string Address { get; set; }
     }

The result picture is:
100035-3.png


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



3.png (24.8 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

In this example, if you click in the adult column, are the rows ordered but this column?

If I don't understand wrong your example, it seems it group the persons in 2 gruoups, adults and childs, but i would prefer don't group, just to can short but the column like with another column.

But it is an interesting option anyway, thanks for share.

0 Votes 0 ·
PeterFleischer-3316 avatar image
1 Vote"
PeterFleischer-3316 answered

Hi,
you can use SortMemberPath with Converter like in following demo:

XAML:

 <Window x:Class="WpfApp1.Window067"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:WpfApp067"
         mc:Ignorable="d"
         Title="Demo sort with converter" Height="450" Width="800">
   <Window.DataContext>
     <local:ViewModel/>
   </Window.DataContext>
   <Window.Resources>
     <local:Int2BoolConverter x:Key="MyConverter"/>
   </Window.Resources>
   <Grid>
     <DataGrid AutoGenerateColumns="False" 
               Margin="5" 
               ItemsSource="{Binding View}">
       <DataGrid.Columns>
         <DataGridCheckBoxColumn Binding="{Binding Col1, Converter={StaticResource MyConverter}}" 
                                 Header="SortColumn" 
                                 SortMemberPath="{Binding Col1, Converter={StaticResource MyConverter}}"/>
         <DataGridTextColumn Binding="{Binding ID}" Header="ID"/>
         <DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
       </DataGrid.Columns>
     </DataGrid>
   </Grid>
 </Window>

ViewModel and converter:

 using System;
 using System.ComponentModel;
 using System.Data;
 using System.Globalization;
 using System.Windows;
 using System.Windows.Data;
    
 namespace WpfApp067
 {
   public class ViewModel
   {
     public ViewModel()
     {
       FillDataTable(dt);
       cvs.Source = dt.DefaultView;
     }
     private DataTable dt = new DataTable();
     private CollectionViewSource cvs = new CollectionViewSource();
     public ICollectionView View { get => cvs.View; }
     private void FillDataTable(DataTable dt)
     {
       dt.Columns.Add("Col1", typeof(int));
       dt.Columns.Add("ID", typeof(int));
       dt.Columns.Add("Name", typeof(string));
       Random rnd = new Random();
       for (int i = 10; i < 30; i++) dt.Rows.Add(rnd.Next(1, 100), i, $"Name {i}");
     }
   }
   public class Int2BoolConverter : IValueConverter
   {
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value > 50;
     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
   }
 }

Result:

102606-x.gif



x.gif (91.6 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.