Seit einiger Zeit beschäftige ich mich mit dem Entity Framework um einen neuen Weg der Datenzugriffschichten zu erleben. Leider muss man bei EDM wirklich noch von "Erleben" reden, da einige Funktionalitäten nicht implementiert sind. So die Unterstützung der Sorting und Filtering Funktionen von QueryObject – Auflistungen.
Da ich auch ein sehr großer Fan von DataBinding (Darunter müssen auch alle Personen in meinem Umfeld leiden), wollte ich die Einfachheit von Entity Framework und WinForm Applikation mit Hilfe von Databinding ausprobieren. Leider mußte ich dann feststellen, dass das BindingSource- Control mit den EntityFramework Klassen klar kommt, aber die Funktionalität für Sortieren und Filtering nicht in der BindingSource Klasse implementiert ist, sondern durchgereicht wird an die gebundende DataSource. Und da liegt das Problem: Die EntityFramework Auflistungs Klassen unterstützen kein Sorting!
Nun kann man darüber philosophieren ob es an dem Entity Framework oder an der BindingSource Klasse liegt, oder einfach eine EntityBindingSource Klasse schreiben:
public class EntityBindingSource : BindingSource, IBindingList
{
private enum Direction {Ascending = 0,Descending = 1 }
private class CompareEntities<T> : IComparer<T>
{
private Direction _sortDirection;
public Direction SortDirection
{
get { return _sortDirection; }
set { _sortDirection = value; }
}
private string _propertyName;
public string PropertyName
{
get { return _propertyName; }
set { _propertyName = value; }
}
public CompareEntities(Direction dir, string fieldName)
{
SortDirection = dir;
PropertyName = fieldName;
}
public int Compare(T x, T y)
{
if (x.GetType().GetProperty(PropertyName) == null)
throw new Exception(String.Format("Given property is not part of the type {0}", PropertyName));
object objX = x.GetType().GetProperty(PropertyName).GetValue(x, null);
object objY = y.GetType().GetProperty(PropertyName).GetValue(y, null);
if (objX == null && objY == null)
return (0);
if (objX == null)
return (-1);
if (objY == null)
return (1);
int retVal = default(int);
if (SortDirection == Direction.Ascending)
retVal = ((IComparable)objX).CompareTo((IComparable)objY);
else
retVal = ((IComparable)objY).CompareTo((IComparable)objX);
return retVal;
}
}
void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
IEnumerable myOrgData = (IEnumerable)DataSource;
List<object> myData = new List<object>();
foreach (object myObj in myOrgData)
myData.Add(myObj);
if (myData.Count < 2)
return;
if (_SortDirection == ListSortDirection.Ascending)
{
_SortDirection = ListSortDirection.Descending;
myData.Sort(new CompareEntities<object>(Direction.Ascending, property.Name));
}
else
{
_SortDirection = ListSortDirection.Ascending;
myData.Sort(new CompareEntities<object>(Direction.Descending, property.Name));
}
_SortProperty = property;
DataSource = myData;
}
private ListSortDirection _SortDirection = ListSortDirection.Ascending;
ListSortDirection IBindingList.SortDirection
{ get
{ return _SortDirection; } }
private PropertyDescriptor _SortProperty = null;
PropertyDescriptor IBindingList.SortProperty
{ get { return (_SortProperty); } }
bool IBindingList.IsSorted
{ get { return (true); } }
bool IBindingList.SupportsSorting
{ get { return (true); }}
}
Das Prinziep dahinter ist ganz einfach, man leitet von der Klasse BindingSource ab und überlädt die Methode
ApplySort diese Methode kommt aus dem interface IBindingList und wird jedesmal aufgerufen, wenn die DataSource sortiert werden soll. Der Rest in dieser Klasse dient dazu eine generichse Sortierung von einer beliebigen Entity Liste durchzuführen. Also nichts besonderes, was Microsoft nicht auch direkt implementieren hätte können. (PS: Und auch bestimmt besser als ich
J)