Nel mondo Windows Forms è ormai consolidato l'utilizzo del componente BindingSource, che semplifica estremamente i meccanismi di interazione con la sorgente dati associata. Una feature molto comoda in particolare riguarda la possibilità di sfruttare funzionalità di searching e sorting qualora la proprietà DataSource del BindingSource abbia assegnato un oggetto che implementi l'interfaccia IBindingList (es. il classico DataView). Ma se dobbiamo ottenere le stesse funzionalità partendo da una collection di oggetti custom, siamo costretti a fornire una nostra implementazione dell'interfaccia IBindingList.
In questo, ci viene in aiuto la classe BindingList (System.ComponentModel), una generica implementazione di IBindingList (a sua volta estensione della più nota interfaccia IList) che supporta opzionalmente le funzionalità di ricerca, ordinamento e notifica a fronte di alcuni semplici override da scriversi in casa.
Nell'esempio qua sotto è riportato il codice per creare una "SearchableBindingList" estendendo una BindingList di oggetti di tipo Customer (che fantasia!):
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;
public class SearchableBindingList<Customer> : BindingList<Customer>
{
public SearchableBindingList() : base() { }
public SearchableBindingList(List<Customer> list) : base(list) { }
protected override bool SupportsSearchingCore
{
get { return true; }
}
protected override int FindCore(PropertyDescriptor prop, object key)
{
PropertyInfo propInfo = typeof(Customer).GetProperty(prop.Name);
Customer item;
if (key != null)
{
for (int i = 0; i < Count; ++i)
{
item = (Customer)Items[i];
if (propInfo.GetValue(item, null).Equals(key)) return i;
}
}
return -1;
}
public int Find(string property, object key)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(Customer));
PropertyDescriptor prop = properties.Find(property, true);
if (prop == null) return -1;
else return FindCore(prop, key);
}
}
Alcune osservazioni:
- Di default la proprietà SupportsSearchingCore vale 'false'. Dobbiamo quindi procedere all'override.
- Il metodo FindCore ritorna l'indice dell'oggetto all'interno della BindingList che possiede il valore key in corrispondenza della proprietà prop del nostro oggetto Customer.
- Il metodo Find è semplicemente una possibile "esposizione" di FindCore.
Finalmente, siamo pronti per il nostro binding verso un BindingSource, che quindi supporterà il Find sulla nostra collection di oggetti di tipo Customer.
// Creazione di una List di oggetti di tipo Customer di esempio
List<Customer> customers = new List<Customer>();
customers.Add(new Customer(1,"Dario Santarelli","xxx@ttt.it"));
customers.Add(new Customer(2,"Mario Rossi","yyy@ttt.it"));
customers.Add(new Customer(3,"Marco Bianchi","zzz@ttt.it"));
// Binding della SearchableBindingList al Binding Source
SearchableBindingList<Customer> sbList = new SearchableBindingList<Customer>(customers);
bindingSource1.DataSource = sbList;
// Il metodo Find invocato sul BindingSource si tradurrà
// in una chiamata al metodo FindCore della SearchableBindingList
bindingSource1.Find("Name", "Dario Santarelli");
Technorati tags: WindowsForms, BindingList