There are times when user wants to see only a limited amount of data in the datagrid. This would obviosuly enhance the performance in case of very large data being that the whole data is not always loaded.

This post shows you how you can use custom filters in C1Datagrid to filter data at server, and hence, improve the performance.
The datasource in this case is a simple collection of objects created at server and assigned to datagrid using a web service.
We will be using LINQ to filter the data collection on the server.
  [DataContract]
public class ServerPerson
{

public ServerPerson(int id)
{

Random _rnd = new Random();
FirstName = DataGenerators.GetString(DataGenerators.GetFirstNames());
LastName = DataGenerators.GetString(DataGenerators.GetLastNames());
Age = _rnd.Next(20,70) id;
Country = DataGenerators.GetString(DataGenerators.GetCountries());
}
private string _firstName;
[DataMember]
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}

private string _lastName;
[DataMember]
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}

private int _age;
[DataMember]
public int Age
{
get { return _age; }
set { _age = value; }
}

private string _country;
[DataMember]
public string Country
{
get { return _country; }
set { _country = value; }
}
}

Since we need to keep the track of the data bound to the datagrid, we use a class with static property. This is a class similar to a viewmodel. We will bind the ItemSource of the datagrid to this static property as simply changing the static property would reflect the changes in the datagrid.



   public class DataGridDataSource
{

private static ObservableCollection _people = new ObservableCollection();
public static ObservableCollection DataSource { get; set; }

public static ObservableCollection DefaultDataSource
{
get
{
GetDefaultData();

return _people;
}
}

private static void GetDefaultData()
{
int _pageSize = 50;
DataWebServiceSoapClient proxy = new DataWebServiceSoapClient(new BasicHttpBinding(), new EndpointAddress(Extensions.GetAbsoluteUri("DataWebService.asmx")));
proxy.GetCurrentDataSourceAsync(_pageSize);

_people.Clear();
proxy.GetCurrentDataSourceCompleted =((s,e)=>
{
foreach (ServerPerson person in e.Result)
{
_people.Add(person);
}
});
}

void proxy_GetCurrentDataSourceCompleted(object sender, GetCurrentDataSourceCompletedEventArgs e)
{
if (e.Result != null)
{
foreach (ServerPerson person in e.Result)
{
_people.Add(person);
}
}
}
}

Binding to ItemSource would be like this:



 peopleDataGrid.SetBinding(C1DataGrid.ItemsSourceProperty, new Binding() { Source = DataGridDataSource.DataSource});

The idea is to bring in the fresh data depending on the filter conditions after the column filter has been changed.
This is done in the CustomFilter class, and depending on the results from the web service, the datagrid source is updated.


Let's see how the WebMethod returning the filtered results would look like.



 [WebMethod]
public List GetTextFilteredDataFromServer(string FilterOperation, string filterstring, string columnname)
{
switch (FilterOperation)
{
case "Contains":
return (from person in CurrentDataSource where person.GetType().GetProperty(columnname).GetValue(person, null).ToString().ToLower().Contains(filterstring.ToLower()) select person).ToList();

case "Starts with":
return (from person in CurrentDataSource where person.GetType().GetProperty(columnname).GetValue(person, null).ToString().ToLower().StartsWith(filterstring.ToLower()) select person).ToList();

case "Equals":
return (from person in CurrentDataSource where person.GetType().GetProperty(columnname).GetValue(person, null).ToString().ToLower().Equals(filterstring.ToLower()) select person).ToList();

case "Not Equals":
return (from person in CurrentDataSource where !person.GetType().GetProperty(columnname).GetValue(person, null).ToString().ToLower().Equals(filterstring.ToLower()) select person).ToList();
}
return null;
}

<pre class="brush: csharp;fontsize: 100; first-line: 1;
[WebMethod]
public List GetTextFilteredDataFromServer(string FilterOperation, string filterstring, string columnname)
{
switch (FilterOperation)
{
case ">

This is how we would update the datasource in CustomFilter class when column filter is changed:



 private void ApplyState(DataGridFilterState filterState)
{
if ((_isLoaded) && (filterState != null) && (filterState.FilterInfo != null)
&& (filterState.FilterInfo.Count > 0) && (filterState.FilterInfo[0] != null))
{
var proxy = new DataWebServiceSoapClient(new BasicHttpBinding(), new EndpointAddress(Extensions.GetAbsoluteUri("DataWebService.asmx")));
proxy.GetTextFilteredDataFromServerCompleted = new EventHandler(proxy_GetTextFilteredDataFromServerCompleted);
proxy.GetTextFilteredDataFromServerAsync(((FilterOperations)_elementOperator.SelectedItem).Value, _elementValue.Text, _owner.FilterMemberPath);
}
}

void proxy_GetTextFilteredDataFromServerCompleted(object sender, GetTextFilteredDataFromServerCompletedEventArgs e)
{
if (e.Result != null)
{
DataGridDataSource.DataSource.Clear();
foreach (var p in e.Result)
DataGridDataSource.DataSource.Add(p);
}
}

We can also implement stealth paging with this scenario.

Download the attached sample for full implementation.

Sample