Advanced User Interface Controls and Components
January 19, 2010
The IntegralUI TreeListView control comes with built-in support for filtering by multiple values using AND, OR criteria and exact or prefix match. Two methods are available:
SetFilter - used to set filter values, matching criteria and whether exact or prefix match is used
SetFilter(string[] values, FilterMatchCriteria criteria, FilterMode mode, bool isPrefixSearch)
ResetFilter - used to set remove the filter values and set the filter to its default state.
ResetFilter()
An array of different values can be applied to the filter. By using different matching criteria: byKey, byTag, byText or byValue, the values are compared with corresponding property values of nodes or subitems. Further more, values are compared using AND or OR operator. By using OR operator, data that is filtered can match more then one value. Finally, during comaprison the values that are used for filtering can be compared using exact or prefix match.
For example: let say we have three different filter values, criteria is set to FilterMatchCriteria.byKey, mode is set to FilterMode.Or and we are using prefix search. Then the data that is shown in TreeListView control will be the nodes or subitems which have their Key property value equal to some of the filter values. During search only the first characters are compared, because we are using prefix search.
In the next section is presented how to create custom drop-down filter for DateTime values.
Let's presume that TreeListView control is placed on the Form with a Button control. The TreeListView control has two columns and some nodes. The first column contains simple text, whether the second column has DateTime values. We will apply filter only for the second column.
To create a drop-down filter, a custom UserControl is used which displays MotnhCalendar control for selecting a month for specified year which will be used to filter the data in TreeListView control. The MonthCalendar control is set to show only months for selection. Here is the code used to create this UserControl:
public partial class FilterDatePanel : UserControl
{
public event EventHandler Close;
private string[] filterDates = null;
public string[] GetValues()
{
return filterDates;
}
public FilterDatePanel()
{
InitializeComponent();
}
protected virtual void OnClose(object sender, EventArgs e)
{
if (Close != null)
Close(this, e);
}
private void btnOk_Click(object sender, EventArgs e)
{
filterDates = new string[] { this.monthCalendar1.SelectedDate.ToString("MMM yyyy") };
OnClose(this, EventArgs.Empty);
}
private void btnCancel_Click(object sender, EventArgs e)
{
filterDates = null;
OnClose(this, EventArgs.Empty);
}
private void FilterDatePanel_Load(object sender, EventArgs e)
{
this.monthCalendar1.AllowDisplayModeChange = false;
}
}
Public Class FilterDatePanel
Public Event Close As EventHandler
Private filterDates As String() = Nothing
Public Function GetValues() As String()
Return filterDates
End Function
Public Sub New()
InitializeComponent()
End Sub
Protected Overridable Sub OnClose(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent Close(Me, e)
End Sub
Private Sub btnOk_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnOk.Click
filterDates = New String() {Me.monthCalendar1.SelectedDate.ToString("MMM yyyy")}
OnClose(Me, EventArgs.Empty)
End Sub
Private Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCancel.Click
filterDates = Nothing
OnClose(Me, EventArgs.Empty)
End Sub
Private Sub FilterDatePanel_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Me.monthCalendar1.AllowDisplayModeChange = False
End Sub
End Class
At first to show the filter panel, a drop-down arrow is added to the right of header of the second column:
column.HeaderContent = "<div><table width=\"100%\"><tr><td>Header " + j.ToString() + "</td><td width=\"80%\" style=\"align:middleright\"><img index=\"0\" width=\"9\" height=\"9\"></img></td></tr></table></div>";
column.HeaderContent = "<div><table width=""100%""><tr><td>Header " & j.ToString() & "</td><td width=""80%"" style=""align:middleright""><img index=""0"" width=""9"" height=""9""></img></td></tr></table></div>"
Whenever, the drop-down arrow is clicked a filter panel will be shown, where a date can be selected. Then this value can be used for filtering the data in TreeListView. Here is the code which presents how the click from drop-down arrow is handled:
private void treeListView1_ContentObjectClicked(object sender, LidorSystems.IntegralUI.ObjectClickEventArgs e)
{
if (e.Object is Image)
{
TreeListViewColumn column = this.treeListView1.GetColumnAt(e.Position.X, e.Position.Y);
if (column != null)
{
Point mousePos = this.treeListView1.PointToScreen(e.Position);
switch (column.Index)
{
case 1:
_popupFilterDate.Show(mousePos);
break;
}
}
}
}
Private Sub treeListView1_ContentObjectClicked(ByVal sender As Object, ByVal e As LidorSystems.IntegralUI.ObjectClickEventArgs) Handles treeListView1.ContentObjectClicked
If TypeOf e.[Object] Is Image Then
Dim column As TreeListViewColumn = Me.treeListView1.GetColumnAt(e.Position.X, e.Position.Y)
If column IsNot Nothing Then
Dim mousePos As Point = Me.treeListView1.PointToScreen(e.Position)
Select Case column.Index
Case 1
_popupFilterDate.Show(mousePos)
Exit Select
End Select
End If
End If
End Sub
Whenever a month is selected and OK button is presed, the selected date is added to the variable which holds the filter values. Also a Close event is created to notify the TreeListView control that filter panel is closed. By handling this event, the filter can be applied to the TreeListView by using the value retrieved from FilterDatePanel.
private void filterDatePanel_Close(object sender, EventArgs e)
{
if (_popupFilterDate != null)
_popupFilterDate.Close(ToolStripDropDownCloseReason.ItemClicked);
}
private void OnFilterDatePanelClosing(object sender, ToolStripDropDownClosingEventArgs e)
{
TreeListViewColumn column = this.treeListView1.GetColumnAt(currentMousePos.X, currentMousePos.Y);
if (column != null)
column.SetFilter(_filterDatePanel.GetValues(), FilterMatchCriteria.byKey, FilterMode.Or, true);
else
{
foreach (TreeListViewColumn currentColumn in this.treeListView1.Columns)
currentColumn.ResetFilter();
}
this.treeListView1.UpdateLayout();
currentMousePos = Point.Empty;
}
private void OnFilterDatePanelOpening(object sender, CancelEventArgs e)
{
currentMousePos = this.treeListView1.PointToClient(Control.MousePosition);
}
Private Sub filterDatePanel_Close(ByVal sender As Object, ByVal e As EventArgs)
If _popupFilterDate IsNot Nothing Then
_popupFilterDate.Close(ToolStripDropDownCloseReason.ItemClicked)
End If
End Sub
Private Sub OnFilterDatePanelClosing(ByVal sender As Object, ByVal e As ToolStripDropDownClosingEventArgs)
Dim column As TreeListViewColumn = Me.treeListView1.GetColumnAt(currentMousePos.X, currentMousePos.Y)
If column IsNot Nothing Then
column.SetFilter(_filterDatePanel.GetValues(), FilterMatchCriteria.byKey, FilterMode.[Or], True)
Else
For Each currentColumn As TreeListViewColumn In Me.treeListView1.Columns
currentColumn.ResetFilter()
Next
End If
Me.treeListView1.UpdateLayout()
currentMousePos = Point.Empty
End Sub
Private Sub OnFilterDatePanelOpening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
currentMousePos = Me.treeListView1.PointToClient(Control.MousePosition)
End Sub
The complete sample project can be downloaded from Download links section.