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 :
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);
}
}
}
The HightLightCell() method is where the Foreground change actually happens. This is done by creating a collection List
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;
}
}
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);
}
};