DataGrid Trier les entêtes des colonnes
Salut,
J'essaye de trouver une méthode pour réussir à faire le tri des entêtes des colonnes...
Je m'explique (avec un exemple vulgarisé)
Imaginons que j'ai ceci comme colonne :
Code:
1 2 3 4 5 6 7
|
<DataGrid.Columns>
<DataGridTextColumn Header="Type" Binding="{Binding ID}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Date" Binding="{Binding RaisingDate}"/>
<DataGridTextColumn Header="Level" Binding="{Binding Level}"/>
</DataGrid.Columns> |
Je voudrais pouvoir de manière dynamique changer l'ordre des mes colonnes en fonction de certaines variables dans mon programme ...
Vous avez une piste ?
tri des entêtes des colonnes d'un datagrid
bonjour rvzip64
Le 1ere probleme :est que les en-tetes sont stores dans la prop Columns du DataGrid -qui est helas en lecture seule(ReadOnly)-donc la lier à un listBox ou un combox finit sur un echec car Mode=TwoWay capote en un simple OneWay,si on essaye de trier les en-tetes.
Le 1er moyen- donne ci-apres -c'est se binder directement à la propriete DisplayIndex de chaque colonne par un control simple ,un textbox .La liaison sur un membre DisplayIndex de la collection Columns fonctionne en mode Mode=TwoWay.
Le 2eme moyen -donne ci-apres- c'est un binding de ListiView sur la collection Columns (listview permet d'afficher à la fois Header et DisplayIndex homologue ).
Les DisplayIndex sont affiches par ListView pour la classe MyClient suivant l'ordre de declaration des props dans la classe (cet ordre est l'ordre "naturel" des index des itemscontrol).
Le ListView "sorte" les index (code msdn)par un click sur l'en-entete colonne. Ensuite un button a ete rajoute pour permettre d'appliquer la modif par code......
code behind et xaml winform (1er moyen) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
//Classes associees Client & ClientFactory
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//needed
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace WpfDataGridSortingHeaderCharp
{
//classe client
class Client : INotifyPropertyChanged
{
public Client ()
{
}
private string m_Type;
public String Type
{
get { return this.m_Type; }
set
{
this.m_Type = value; NotifyPropertyChanged("Type");
}
}
private string m_Name;
public String Name
{
get { return this.m_Name; }
set
{
this.m_Name = value; NotifyPropertyChanged("Name");
}
}
private DateTime m_RaisingDate;
public DateTime RaisingDate
{
get { return this.m_RaisingDate; }
set
{
this.m_RaisingDate = value; NotifyPropertyChanged("RaisingDate");
}
}
private int m_Level;
public int Level
{
get { return this.m_Level; }
set
{
this.m_Level = value; NotifyPropertyChanged("Level");
}
}
#region INotifyPropertyChanged Membres
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
//factory clients
class ClientFactory
{
private static Client cl=new Client() ;
private static ObservableCollection<Client> m_lstClients;
public ClientFactory ()
{
}
public static ObservableCollection<Client> GetClients()
{
ClientFactory.m_lstClients = new ObservableCollection<Client>();
for (int i = 0; i < 6; i++)
{
cl = new Client();
cl.Name = "client" + (i + 1).ToString();
cl.Type = "ID" + (i + 1).ToString();
cl.RaisingDate = DateTime.Now;
cl.Level = i + 1;
ClientFactory.m_lstClients.Add(cl);
}
return ClientFactory.m_lstClients;
}
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| //code behind winform
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfDataGridSortingHeaderCharp
{
/// <summary>
/// Logique d'interaction pour Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| //code xaml winform
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
xmlns:local="clr-namespace:WpfDataGridSortingHeader"
Title="Window1" Height="320" Width="320">
<Window.Resources>
<ObjectDataProvider
x:Key="myDataSource"
MethodName="GetClients"
ObjectType="{x:Type local:ClientFactory}">
</ObjectDataProvider>
<!--This object 'spies' on the DataContext for other elements.-->
<local:DataContextSpy x:Key="Spy" />
</Window.Resources>
<Grid
DataContext="{Binding Source={StaticResource myDataSource}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="100"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<my:DataGrid
Grid.Row="0"
AutoGenerateColumns="False"
Name="DataGrid1"
Height="150"
VerticalAlignment="Center"
AlternationCount="0"
CanUserSortColumns="True"
ItemsSource="{Binding }">
<my:DataGrid.Columns>
<my:DataGridTextColumn
x:Name="myType"
Header="Type"
Binding="{Binding Type}"/>
<my:DataGridTextColumn
x:Name="myName"
Header="Name"
Binding="{Binding Name}"/>
<my:DataGridTextColumn
x:Name="myDate"
Header="Date"
Binding="{Binding RaisingDate}"/>
<my:DataGridTextColumn
x:Name="myLevel"
Header="Level"
Binding="{Binding Level}"/>
</my:DataGrid.Columns>
</my:DataGrid>
<Grid
Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="32"></RowDefinition>
<RowDefinition Height="*" MinHeight="32"></RowDefinition>
<RowDefinition Height="*" MinHeight="32"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label
Grid.Row="0"
Grid.Column="0"
Name="HeaderRaisingDate"
HorizontalAlignment="Stretch"
Height="32"
Background="LightGreen"
BorderBrush="Red"
Content="{Binding ElementName=myDate,Path=Header,Mode=TwoWay}">
</Label>
<Label
Grid.Row="0"
Grid.Column="1"
Name="HeaderName"
Height="32"
HorizontalAlignment="Stretch"
BorderBrush="Red"
Background="LightCoral"
Content="{Binding ElementName=myName,Path=Header,Mode=TwoWay}">
</Label>
<TextBox
Grid.Row="1"
Grid.Column="0"
Name="txtDate"
HorizontalAlignment="Stretch"
Height="32"
Background="LightGreen"
BorderBrush="Red"
Text="{Binding ElementName=myDate,Path=DisplayIndex,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<TextBox
Grid.Row="1"
Grid.Column="1"
Name="txtName"
Height="32"
HorizontalAlignment="Stretch"
BorderBrush="Red"
Background="LightCoral"
Text="{Binding ElementName=myName,Path=DisplayIndex,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
</Grid>
</Grid>
</Window> |
code 2eme moyen :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
//Classes associees MyClient & MyClientFactory
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//needed
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace WpfDataGridSortingHeaderCharp
{
//classe client
class MyClient : INotifyPropertyChanged
{
public MyClient()
{
}
private string m_Type;
public String Type
{
get { return this.m_Type; }
set
{
this.m_Type = value; NotifyPropertyChanged("Type");
}
}
private string m_Name;
public String Name
{
get { return this.m_Name; }
set
{
this.m_Name = value; NotifyPropertyChanged("Name");
}
}
private DateTime m_RaisingDate;
public DateTime RaisingDate
{
get { return this.m_RaisingDate; }
set
{
this.m_RaisingDate = value; NotifyPropertyChanged("RaisingDate");
}
}
private int m_Level;
public int Level
{
get { return this.m_Level; }
set
{
this.m_Level = value; NotifyPropertyChanged("Level");
}
}
#region INotifyPropertyChanged Membres
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
//factory clients
class MyClientFactory
{
private static ObservableCollection<MyClient> MyClients;
public MyClientFactory()
{
}
public static ObservableCollection<MyClient> GetMyClients()
{
MyClientFactory.MyClients = new ObservableCollection<MyClient>();
MyClient cl;
for (int i = 0; i < 10; i++)
{
cl = new MyClient();
cl.Name = "myClient" + (i + 1).ToString();
cl.Type = "ID" + (i + 1).ToString();
cl.RaisingDate = DateTime.Now;
cl.Level = i + 1;
MyClientFactory.MyClients.Add(cl);
}
return MyClientFactory.MyClients;
}
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| //Code behind winform
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using Microsoft.Windows.Controls;
namespace WpfDataGridSortingHeaderCharp
{
/// <summary>
/// Logique d'interaction pour Window2.xaml
/// </summary>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
GridViewColumnHeader _lastHeaderClicked = null;
ListSortDirection _lastDirection = ListSortDirection.Ascending;
private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
{
GridViewColumnHeader headerClicked =
e.OriginalSource as GridViewColumnHeader;
ListSortDirection direction;
if (headerClicked != null)
{
if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
{
if (headerClicked != _lastHeaderClicked)
{
direction = ListSortDirection.Ascending;
}
else
{
if (_lastDirection == ListSortDirection.Ascending)
{
direction = ListSortDirection.Descending;
}
else
{
direction = ListSortDirection.Ascending;
}
}
string header = headerClicked.Column.Header as string;
Sort(header, direction);
if (direction == ListSortDirection.Ascending)
{
headerClicked.Column.HeaderTemplate =
Resources["HeaderTemplateArrowUp"] as DataTemplate;
}
else
{
headerClicked.Column.HeaderTemplate =
Resources["HeaderTemplateArrowDown"] as DataTemplate;
}
// Remove arrow from previously sorted header
if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
{
_lastHeaderClicked.Column.HeaderTemplate = null;
}
_lastHeaderClicked = headerClicked;
_lastDirection = direction;
}
}
}
private void Sort(string sortBy, ListSortDirection direction)
{
ICollectionView dataView =
CollectionViewSource.GetDefaultView(this.myListView.ItemsSource);
dataView.SortDescriptions.Clear();
SortDescription sd = new SortDescription(sortBy, direction);
dataView.SortDescriptions.Add(sd);
dataView.Refresh();
}
private void btnTri_Click(object sender, RoutedEventArgs e)
{
// Apply Sort Order of myListView to the Columns objects by their Header property.
int i = 0;
foreach (DataGridColumn col in this.DataGrid1.Columns)
{
DataGridTextColumn DGDText = (DataGridTextColumn)this.myListView.Items[i];
col.DisplayIndex = DGDText.DisplayIndex;
i = i + 1;
}
}
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| //Code xaml winform
<Window x:Class="WpfDataGridSortingHeaderCharp.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:WpfDataGridSortingHeaderCharp"
Title="Sort Header Column with ListView" Height="300" Width="457">
<Window.Resources>
<DataTemplate x:Key="HeaderTemplateArrowUp">
<DockPanel>
<TextBlock HorizontalAlignment="Center" Text="{Binding}"/>
<Path x:Name="arrow"
StrokeThickness = "1"
Fill = "gray"
Data = "M 5,10 L 15,10 L 10,5 L 5,10"/>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="HeaderTemplateArrowDown">
<DockPanel>
<TextBlock HorizontalAlignment="Center" Text="{Binding }"/>
<Path x:Name="arrow"
StrokeThickness = "1"
Fill = "gray"
Data = "M 5,5 L 10,10 L 15,5 L 5,5"/>
</DockPanel>
</DataTemplate>
<ObjectDataProvider
x:Key="myDataSource"
MethodName="GetMyClients"
ObjectType="{x:Type local:MyClientFactory}">
</ObjectDataProvider>
</Window.Resources>
<Grid
DataContext="{Binding Source={StaticResource myDataSource}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="100"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<my:DataGrid
Grid.Row="0"
AutoGenerateColumns="False"
Name="DataGrid1"
Height="150"
VerticalAlignment="Center"
AlternationCount="0"
CanUserSortColumns="True"
ItemsSource="{Binding}">
<my:DataGrid.Columns>
<my:DataGridTextColumn
x:Name="Type"
Header="Type"
Binding="{Binding Path=Type}"/>
<my:DataGridTextColumn
x:Name="Name"
Header="Name"
Binding="{Binding Path=Name}"/>
<my:DataGridTextColumn
x:Name="Date"
Header="Date"
Binding="{Binding Path=RaisingDate}"/>
<my:DataGridTextColumn
x:Name="Level"
Header="Level"
Binding="{Binding Path=Level}"/>
</my:DataGrid.Columns>
</my:DataGrid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="32" ></RowDefinition>
<RowDefinition Height="32*" ></RowDefinition>
<RowDefinition Height="32" ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="20*"></ColumnDefinition>
<ColumnDefinition Width="60"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label
Grid.Row="0"
Grid.Column="0"
Name="lblRisingDate"
Background="LightYellow"
BorderBrush="Red"
FontSize="12"
FontWeight ="Bold"
HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="Textbox Binde à Col3 (RisingDate) " >
</Label>
<!--TextBox binde à DisplayIndex et permettant de modifier le DisplayIndex
d'un DataGridColum-->
<TextBox
Grid.Row="0"
Grid.Column="2"
Name="txtRisingDate"
Background="LavenderBlush"
BorderBrush="Red"
FontSize="12"
FontWeight ="Bold"
Width="60"
HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Text="{Binding ElementName=Date,Path=DisplayIndex,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
<!--ListView binde à la collection Columns en lecture seule
permettant de trier les Headers du DataGrid-->
<ListView
Grid.Row="1"
Grid.ColumnSpan="3"
Name="myListView"
Background="LightSalmon"
Foreground="White"
FontSize="12"
FontWeight ="Bold"
ToolTip="myHeaders"
GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
ItemsSource="{Binding ElementName=DataGrid1,Path=Columns}">
<ListView.View>
<GridView>
<GridViewColumn
Header="Header"
Width="100"
DisplayMemberBinding="{Binding Path=Header,Mode=TwoWay}" />
<GridViewColumn
Header="DisplayIndex"
Width="100"
DisplayMemberBinding="{Binding Path=DisplayIndex,Mode=TwoWay}" />
</GridView>
</ListView.View>
</ListView>
<!--Button permettant d'appliquer l'ordre de tri des Headers
effectue par le ListView en ordre de tri des DisplayIndex
des colonnes du DataGrid-->
<Button
Grid.Row="2"
Grid.ColumnSpan="3"
Name="btnTri"
Width="100"
Content="TriHeader"
Click="btnTri_Click">
</Button>
</Grid>
</Grid>
</Window> |
bon code.................