Many of our users often requested on how to highlight searched text with changed Foreground in Silverlight Flexgrid. This blog explains a simple approach to do this. The implementation involves following steps :

  1. Create a customized Cell Factory class which has a constructor that accepts the text being searched.
  2. Use HighLightCell() method to hightlight searched text.
  3. Assign the custom CellFactory object to C1FlexGrid CellFactory property.

Custom CellFactory Class

To create custom cells, you have to create a class that implements the ICellFactory interface and assign this class to the grid's CellFactory property. Like custom columns, custom ICellFactory classes can be highly specialized and application-specific, or they can be general, reusable, configurable classes. In general, custom ICellFactory classes are a lot simpler than custom columns since they deal directly with cells (columns, by contrast, need to deal with the columns themselves and also with the cells and other objects contained in the column).

public class MyCellFactory : C1.Silverlight.FlexGrid.CellFactory  
{  
private string _text;  
public MyCellFactory()  
{ }  
public MyCellFactory(string searchString)  
{  
_text = searchString;  
}  
public override void CreateCellContent(C1.Silverlight.FlexGrid.C1FlexGrid grid, Border bdr, C1.Silverlight.FlexGrid.CellRange range)  
{  
base.CreateCellContent(grid, bdr, range);  
var tb = bdr.Child as TextBlock;  
if (tb != null)  
HighlightCell(tb);  
}  

}  
}

HightLightCell() Method

The HightLightCell() method is where the Foreground change actually happens. This is done by creating a collection List that consists of the text preceding the text being searched, the actual text being searched and the remaining text. The text appearing before and after the searched text is added to the Inline collection of the TextBlock without any change. The text being searched is also added to the TextBlock's Inline collection, however, with its Foreground changed. Here is the complete code for the Custom Cell Factory


public class MyCellFactory : C1.Silverlight.FlexGrid.CellFactory  
{  
 private string _text;  
 public MyCellFactory()  
 { }  
 public MyCellFactory(string searchString)  
 {  
   _text = searchString;  
 }  
 public override void CreateCellContent(C1.Silverlight.FlexGrid.C1FlexGrid grid, Border bdr, C1.Silverlight.FlexGrid.CellRange range)  
 {  
  base.CreateCellContent(grid, bdr, range);  
  var tb = bdr.Child as TextBlock;  
  if (tb != null)  
  HighlightCell(tb);  
 }  

 private void HighlightCell(TextBlock tb)  
 {  
  if (string.Empty != _text)  
  {  
   var stringContent = tb.Text;  
   if (stringContent.ToLower().Contains(_text.ToLower()))  
   {  
    var runsToHighlight = new List<Run>();  
    var newInlines = BuildRuns(stringContent, _text, runsToHighlight);  
    // apply new splitted InlineCollection  
    tb.Inlines.Clear();  
    foreach (var il in newInlines) tb.Inlines.Add(il);  
    // apply styles:  
    // red color to the matching text  
    // Bold FontWeight too  
    foreach (var r in runsToHighlight)  
    {  
     r.Foreground = new SolidColorBrush(Colors.Red);  
     r.FontWeight = FontWeights.Bold;  
    }  
   }  
  }  
 }  

 private List<Run> BuildRuns(string text, string filterText, List<Run> runsToHighlight)  
 {  
  var runs = new List<Run>();  
  int i = 0;  

  while (i < text.Length)  
  {  
   var pos = text.IndexOf(filterText, i, StringComparison.CurrentCultureIgnoreCase);  
   // not matching text in the head  
   if (i < pos)  
    runs.Add(new Run() { Text = text.Substring(i, pos - i) });  

   if (pos == -1)  
   {  
    // not matching text in the tail  
    runs.Add(new Run() { Text = text.Substring(i) });  
    i = text.Length;  
   }  
   else  
   {  
    // new matching text  
    var hRun = new Run() { Text = text.Substring(pos, filterText.Length) };  
    runs.Add(hRun);  
    runsToHighlight.Add(hRun);  
    i = pos + filterText.Length;  
   }  
  }  
  return runs;  
 }  
}  

Setting C1Flexgrid.CellFactory

Now, we need to set an instance of this class as the value of C1Flexgrid's CellFactory property. However, here we do it twice. At a button click event and also at KeyDown event of the TextBox that accepts the search string.


//Search at "Find" button click  
button1.Click += (s, e) =>  
 {  
  _text = this.textBox1.Text;  
  //refresh grid each time button is clicked for a new search  
  c1FlexGrid1.CellFactory = new MyCellFactory(_text);  
 };  

//Search at "Enter" keydown  
textBox1.KeyDown += (s, e) =>  
 {  
  if (e.Key == Key.Enter)  
  {  
   _text = this.textBox1.Text;  
   c1FlexGrid1.CellFactory = new MyCellFactory(_text);  
  }  
 };  

Download VB Sample Download CS Sample