Mapping de données par attributs de Michel Perfetti : BONUS
Suite à l'excellent article de Michel Perfetti...
Pour ceux qui voudrait ajouter à la fois le tri et le binding à leur collection, au lieu de la simple BindingList, utilisez cette implémentation (ListeTriee) :
public class PropertyComparer<T> : IComparer<T>
{
private PropertyDescriptor _sortPropertyCore;
private ListSortDirection _sortDirectionCore;
public PropertyComparer(PropertyDescriptor SortPropertyCore, ListSortDirection SortDirectionCore)
{
_sortPropertyCore = SortPropertyCore;
_sortDirectionCore = SortDirectionCore;
}
int IComparer<T>.Compare(T obj1, T obj2)
{
int retour;
object obj1Value = obj1.GetType().GetProperty(_sortPropertyCore.Name).GetValue(obj1, null);
object obj2Value = obj2.GetType().GetProperty(_sortPropertyCore.Name).GetValue(obj2, null);
//si la valeur peut être comparée
if (obj1Value is IComparable)
{
retour = ((IComparable)obj1Value).CompareTo(obj2Value);
}
// sinon on compare les string() de l'objet
else if (obj1Value != null && obj2Value != null)
retour = obj1Value.ToString().CompareTo(obj2Value.ToString());
else
retour = 0;
//ordres de tri
if (_sortDirectionCore == ListSortDirection.Ascending)
{
return retour;
}
else
{
return -retour;
}
}
}
public class ListeTriee<T> : BindingList<T>, IComponent
{
private PropertyDescriptor _sortPropertyCore;
private ListSortDirection _sortDirectionCore;
private bool _isSortedCore;
//supporte le tri
protected override bool SupportsSortingCore
{
get { return true; }
}
//sens du tri
protected override ListSortDirection SortDirectionCore
{
get { return _sortDirectionCore; }
}
//Propriété courante triée
protected override PropertyDescriptor SortPropertyCore
{
get { return _sortPropertyCore; }
}
//La collection est t-elle triée?
protected override bool IsSortedCore
{
get { return _isSortedCore; }
}
//appliquer un tri sur une propriété et dans un sens déterminé
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
_sortPropertyCore = prop;
_sortDirectionCore = direction;
//on récupère la collection courante
List<T> _items = this.Items as List<T>;
if (_items != null)
{
PropertyComparer<T> pc = new PropertyComparer<T>(_sortPropertyCore, _sortDirectionCore);
//tri
_items.Sort(pc);
_isSortedCore = true;
}
else
{
_isSortedCore = false;
}
// pour la notification du binding
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
public event EventHandler Disposed;
private ISite m_Site;
public ISite Site
{
get
{
return m_Site;
}
set
{
m_Site = value;
}
}
public void Dispose()
{
this.Items.Clear();
Disposed(this, System.EventArgs.Empty);
}
}
Ensuite il vous suffit de rajouter la méthode dans la classe Mapper<T> de Michel :
public ListeTriee<T> ExtractListeTrieeFromIDataReader(IDataReader reader)
{
ListeTriee<T> result = new ListeTriee<T>();
MapIDataReader(reader, result);
return result;
}
L'utilisation est simple, par exemple :
public ListeTriee<AgentENT> GetAgentCollection(int AgenceID)
{
ListeTriee<AgentENT> l;
using (SqlConnection c = new SqlConnection(_chaineConnexion))
{
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Agent WHERE Agence_ID = @AgenceID Order by Agent_Nom ", c))
{
//définition des paramètres
cmd.Parameters.Add("@AgenceID", SqlDbType.Int);
//passage des valeurs
cmd.Parameters["@AgenceID"].Value = AgenceID;
c.Open();
Mapper<AgentENT> mapper = new Mapper<AgentENT>();
using (SqlDataReader reader = cmd.ExecuteReader())
{
l = mapper.ExtractListeTrieeFromIDataReader(reader);
reader.Close();
}
c.Close();
}
}
return l;
}
Maintenant, vous n'avez plus d'excuses, si vous continuez à utiliser du DataSet à tout va...
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :