Synchronize RadGridView and RadBindingNavigator after Filtering and Sorting
Environment
| Product Version | Product | Author |
|---|---|---|
| 2019.2.618 | RadGridView for WinForms | Desislava Yordanova |
Description
Consider that you have a RadGridView and a RadBindingNavigator bound to the same BindingSource. RadBindingNavigator allows you to iterate the grid rows in an easier way. However, if you sort the grid, RadBindingNavigator keeps traversing the records in their original order. If you filter the grid, the number of records is not updated in RadBindignNavigator. The following gif file illustrates better the undesired behavior:

Solution
This behavior is normal. RadBindingNavigator and the standard MS BindingNavigator uses the CurrencyManager to navigate through the records. However, when the RadGridView is sorted/filtered, its child rows are reordered/filtered according to the current SortDescriptor/FilterDescriptor. When clicking the next button in the binding navigator, it will navigate to the next record in the original data order. That is why you obtain the "jumping" in a sorted RadGridView.
This article demonstrates a sample code snippet how to filter the binding navigator as well and traverse the records in the same order they appear in the grid. The obtained result is illustrated in the below gif file:

It is necessary to handle the RadGridView.FilterExpressionChanged event and apply the same filter expression to RadBindingNavigator. As to the sorting behavior, it is necessary to use a custom implementation for RadBindingNavigator as it is demonstrated below:
private void RadForm1_Load(object sender, EventArgs e)
{
this.productsTableAdapter.Fill(this.nwindDataSet.Products);
this.radGridView1.DataSource = this.productsBindingSource;
this.radGridView1.BestFitColumns();
this.radGridView1.EnableFiltering = true;
this.radBindingNavigator1.BindingSource = this.productsBindingSource;
this.radGridView1.FilterExpressionChanged += Grid_FilterExpressionChanged;
this.radGridView1.SortChanged += radGridView1_SortChanged;
}
private void Grid_FilterExpressionChanged(object sender, FilterExpressionChangedEventArgs e)
{
this.productsBindingSource.Filter = e.FilterExpression;
}
private void radGridView1_SortChanged(object sender, GridViewCollectionChangedEventArgs e)
{
this.productsBindingSource.Sort = e.GridViewTemplate.SortDescriptors.Expression;
}
public class CustomBindingNavigator : RadBindingNavigator
{
protected override RadBindingNavigatorElement CreateNavigatorElement()
{
return new CustomBindingNavigatorElement();
}
public class CustomBindingNavigatorElement : RadBindingNavigatorElement
{
protected override void FirstButton_Click(object sender, EventArgs e)
{
Form f = this.ElementTree.Control.FindForm();
if (f != null)
{
RadGridView grid = f.Controls[0] as RadGridView;
grid.GridNavigator.SelectFirstRow();
}
}
protected override void LastButton_Click(object sender, EventArgs e)
{
Form f = this.ElementTree.Control.FindForm();
if (f != null)
{
RadGridView grid = f.Controls[0] as RadGridView;
grid.GridNavigator.SelectLastRow();
}
}
protected override void PreviousButton_Click(object sender, EventArgs e)
{
Form f = this.ElementTree.Control.FindForm();
if (f != null)
{
RadGridView grid = f.Controls[0] as RadGridView;
grid.GridNavigator.SelectPreviousRow(1);
}
}
protected override void NextButton_Click(object sender, EventArgs e)
{
Form f = this.ElementTree.Control.FindForm();
if (f != null)
{
RadGridView grid = f.Controls[0] as RadGridView;
grid.GridNavigator.SelectNextRow(1);
}
}
}
}