пятница, мая 11, 2007

Пример реализации IBindingListView в Sooda

Первый пост в моём блоге посвящён реализации интерфейса IBindingListView в коллекциях Sooda.
В ходе разработки текущего проекта возникла необходимость фильтрации и сортировки коллекции в DataGridView.
Дабы долго не ломать голову над тем, в каком классе мне реализовывать этот интерфейс - выбрал тот, в котором эта реализация наиболее была необходима мне.

И так, берем класс SoodaObjectCollectionWrapper и делаем его производным от IBindingListView:


public class SoodaObjectCollectionWrapper : ISoodaObjectList, ISoodaObjectListInternal, IBindingListView
{

и добавляем определение методов интерфейса:


#region IBindingListView Members

private string m_FilterString = String.Empty;
private bool m_Filtered=false, m_Sorted =false;
private ISoodaObjectList m_OriginalCollection = new SoodaObjectListSnapshot();
[NonSerialized]
private PropertyDescriptor m_sortBy = null;
private ListSortDirection m_sortDirection = ListSortDirection.Ascending;

string IBindingListView.Filter
{
get
{
return m_FilterString;
}
set
{
string old = m_FilterString;
m_FilterString = value;
Console.WriteLine("set to '{0}'", value);
//if (m_FilterString != old)
//{
UpdateFilter();
//}
}
}

void IBindingListView.RemoveFilter()
{
Console.WriteLine("Removed");
if (!m_Filtered)
return;
m_FilterString = null;
m_Filtered = false;
m_Sorted = false;
Clear();
foreach (object item in m_OriginalCollection)
{
_theList.Add(item);
}
m_OriginalCollection.Clear();
}

protected virtual void UpdateFilter()
{
if (m_OriginalCollection.Count == 0)
{
foreach (object item in this)
{
m_OriginalCollection.Add(item);
}
}

ISoodaObjectList tCollection =
m_OriginalCollection.Filter((m_FilterString == string.Empty) || (m_FilterString == null)
? new SoodaWhereClause()
: new SoodaWhereClause(
m_FilterString.Replace("[", string.Empty).Replace("]", string.Empty).Trim()));

Clear();

foreach (object item in tCollection)
{
_theList.Add(item);
}

m_Filtered = true;

OnListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, -1));
}

public bool SupportsFiltering
{
get { return true; }
}

public void ApplySort(ListSortDescriptionCollection sorts)
{
throw new Exception("The method or operation is not implemented.");
}

public ListSortDescriptionCollection SortDescriptions
{
get { throw new Exception("The method or operation is not implemented."); }
}

public bool SupportsAdvancedSorting
{
get { throw new Exception("The method or operation is not implemented."); }
}

#endregion

#region IBindingList Members

public void AddIndex(PropertyDescriptor property)
{
throw new Exception("The method or operation is not implemented.");
}

public object AddNew()
{
throw new Exception("The method or operation is not implemented.");
}

public bool AllowEdit
{
get { return false; }
}

public bool AllowNew
{
get { return false; }
}

public bool AllowRemove
{
get { return false; }
}

public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
string sortOrder = property.Name + (direction == ListSortDirection.Ascending ? " asc" : " desc");
_theList = _theList.Sort(SoodaOrderBy.Parse(sortOrder).GetComparer());
m_sortBy = property;
m_Sorted = true;
m_sortDirection = direction;
OnListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, 0));
}

public int Find(PropertyDescriptor property, object key)
{
foreach (object o in this)
{
object a = property.GetValue(o);

if (a == null && key == null) return this.IndexOf(o);
if (a == null || key == null) continue;
if (((IComparable)a).CompareTo(key) == 0)
return this.IndexOf(o);
}
return -1;
}

public bool IsSorted
{
get { return m_Sorted; }
}

protected void OnListChanged(object sender, ListChangedEventArgs e)
{
if (_listChanged != null)
{
_listChanged(sender, e);
}
}

private ListChangedEventHandler _listChanged;
event ListChangedEventHandler IBindingList.ListChanged
{
add { _listChanged += value; }
remove { _listChanged -= value; }
}

public void RemoveIndex(PropertyDescriptor property)
{
throw new Exception("The method or operation is not implemented.");
}

public void RemoveSort()
{
m_sortBy = null;
m_Sorted = false;
}

public ListSortDirection SortDirection
{
get { return m_sortDirection; }
}

public PropertyDescriptor SortProperty
{
get { return m_sortBy; }
}

public bool SupportsChangeNotification
{
get { return false; }
}

public bool SupportsSearching
{
get { return true; }
}

public bool SupportsSorting
{
get { return true; }
}

#endregion

Некоторые методы я пока оставил нереализованными, но чтобы не возникло проблем в дальнейшем я оставил себе напоминание в виде эксепшинов ("The method or operation is not implemented."). И если для каких либо целей CLR вызовет один из неопределенных методов - это будет сигналом для меня...