Telerik UI for ASP.NET AJAX

This online demo illustrates how to use a header context menu in RadGrid for ASP.NET AJAX. It is quite useful if you would like to process operations like sorting or grouping on a per-column basis or show/hide some of the grid columns based on the end user's preferences.

grid headercontextmenu

The header context menu exposes the following default options:

  • Sort the column data in ascending/descending/none order.

  • Group/ungroup the column data in case the grouping feature of the control is enabled.

  • Show/hide grid columns client-side by changing the state of the checkboxes beside each column name. This feature can be seen drilling down to the second menu group under the 'Columns' option).

  • Filter the column data on two conditions related with a logical AND operator.

This context menu can be enabled by setting the EnableHeaderContextMenu property of the corresponding table to true (the default value is false). The menu is designed on a per-table basis and can be switched on/off for different levels in a hierarchical grid on demand. In this example the header context menu is disabled for the second level in the hierarchy.

Note that the items from the menu will be displayed dynamically depending on the grid configuration. For example, if the grouping feature is disabled the 'Group By'/'Ungroup' options will be hidden, or if you choose not to use natural sorting (AllowNaturalSort=false) the 'Clear Sorting' item will be absent.

The code snippets from the example are below:

CopyASPX
<telerik:RadScriptManager ID="RadScriptManager1" runat="server">
</telerik:RadScriptManager>
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
  <AjaxSettings>
    <telerik:AjaxSetting AjaxControlID="RadGrid1">
      <UpdatedControls>
        <telerik:AjaxUpdatedControl ControlID="RadGrid1" />
      </UpdatedControls>
    </telerik:AjaxSetting>
  </AjaxSettings>
</telerik:RadAjaxManager>
<telerik:RadGrid ID="RadGrid1" Skin="Office2007" ShowGroupPanel="True" ShowStatusBar="true"
  runat="server" DataSourceID="SqlDataSource1" Width="95%" AutoGenerateColumns="False"
  PageSize="3" AllowSorting="True" AllowMultiRowSelection="False" AllowPaging="True"
  GridLines="None">
  <PagerStyle Mode="NextPrevAndNumeric"></PagerStyle>
  <MasterTableView Width="100%" DataSourceID="SqlDataSource1" DataKeyNames="CustomerID"
    AllowMultiColumnSorting="True" EnableHeaderContextMenu="true" TableLayout="Fixed">
    <DetailTables>
      <telerik:GridTableView DataKeyNames="OrderID" DataSourceID="SqlDataSource2" Width="100%"
        runat="server" EnableHeaderContextMenu="false" TableLayout="Fixed">
        <ParentTableRelation>
          <telerik:GridRelationFields DetailKeyField="CustomerID" MasterKeyField="CustomerID" />
        </ParentTableRelation>
        <DetailTables>
          <telerik:GridTableView DataKeyNames="OrderID" DataSourceID="SqlDataSource3" Width="100%"
            runat="server" EnableHeaderContextMenu="true" TableLayout="Fixed">
            <ParentTableRelation>
              <telerik:GridRelationFields DetailKeyField="OrderID" MasterKeyField="OrderID" />
            </ParentTableRelation>
            <Columns>
              <telerik:GridBoundColumn SortExpression="UnitPrice" HeaderText="Unit Price" DataField="UnitPrice"
                UniqueName="UnitPrice">
              </telerik:GridBoundColumn>
              <telerik:GridBoundColumn SortExpression="Quantity" HeaderText="Quantity" DataField="Quantity"
                UniqueName="Quantity">
              </telerik:GridBoundColumn>
              <telerik:GridBoundColumn SortExpression="Discount" HeaderText="Discount" DataField="Discount"
                UniqueName="Discount">
              </telerik:GridBoundColumn>
            </Columns>
            <GroupByExpressions>
              <telerik:GridGroupByExpression>
                <SelectFields>
                  <telerik:GridGroupByField FieldAlias="Quantity" FieldName="Quantity" FormatString=""
                    HeaderText=""></telerik:GridGroupByField>
                </SelectFields>
                <GroupByFields>
                  <telerik:GridGroupByField FieldAlias="Quantity" FieldName="Quantity" FormatString=""
                    HeaderText=""></telerik:GridGroupByField>
                </GroupByFields>
              </telerik:GridGroupByExpression>
            </GroupByExpressions>
          </telerik:GridTableView>
        </DetailTables>
        <Columns>
          <telerik:GridBoundColumn SortExpression="OrderID" HeaderText="OrderID" DataField="OrderID"
            UniqueName="OrderID">
          </telerik:GridBoundColumn>
          <telerik:GridBoundColumn SortExpression="OrderDate" HeaderText="Date Ordered" DataField="OrderDate"
            UniqueName="OrderDate">
          </telerik:GridBoundColumn>
          <telerik:GridBoundColumn SortExpression="EmployeeID" HeaderText="EmployeeID" DataField="EmployeeID"
            UniqueName="EmployeeID">
          </telerik:GridBoundColumn>
        </Columns>
      </telerik:GridTableView>
    </DetailTables>
    <Columns>
      <telerik:GridBoundColumn SortExpression="CustomerID" HeaderText="CustomerID" DataField="CustomerID"
        UniqueName="CustomerID">
      </telerik:GridBoundColumn>
      <telerik:GridBoundColumn SortExpression="ContactName" HeaderText="Contact Name" DataField="ContactName"
        UniqueName="ContactName" Groupable="false">
      </telerik:GridBoundColumn>
      <telerik:GridBoundColumn SortExpression="CompanyName" HeaderText="Company" DataField="CompanyName"
        UniqueName="CompanyName">
      </telerik:GridBoundColumn>
    </Columns>
  </MasterTableView>
  <ClientSettings ReorderColumnsOnClient="True" AllowDragToGroup="True" AllowColumnsReorder="True">
    <Resizing AllowRowResize="True" AllowColumnResize="True"></Resizing>
  </ClientSettings>
</telerik:RadGrid><br />
<br />
<asp:SqlDataSource ID="SqlDataSource1" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
  ProviderName="System.Data.SqlClient" SelectCommand="SELECT * FROM Customers" runat="server">
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
  ProviderName="System.Data.SqlClient" SelectCommand="SELECT * FROM Orders Where CustomerID = @CustomerID"
  runat="server">
  <SelectParameters>
    <asp:SessionParameter Name="CustomerID" SessionField="CustomerID" Type="string" />
  </SelectParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource3" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
  ProviderName="System.Data.SqlClient" SelectCommand="SELECT * FROM [Order Details] where OrderID = @OrderID"
  runat="server">
  <SelectParameters>
    <asp:SessionParameter Name="OrderID" SessionField="OrderID" Type="Int32" />
  </SelectParameters>
</asp:SqlDataSource>

Using header context menu for filtering

As of Q1 2010 RadGrid is equipped with a new filtering menu. It will be a sub-part of RadGrid's header context menu and will allow for filtering the grid's data on two conditions related with a logical AND operator. To switched on/off header context filter menu a new property has been introduced into the RadGrid control -RadGrid.EnableHeaderContextFilterMenu/GridTableView.EnableHeaderContextFilterMenu. In addition, it is important that RadGrid.EnableHeaderContextMenu/GridTableView.EnableHeaderContextMenu and RadGrid.AllowFilteringByColumn/GridTableView.AllowFilteringByColumn properties be set to true in order for the header context filter menu to be available. For the purpose of supporting this extension to RadGrid's filtering mechanism, each GridColumn will feature an additional current filter function/value properties that are set to contain the second filter condition data. These properties are called AndCurrentFilterFunction/AndCurrentFilterValue:

CopyASPX
<telerik:GridBoundColumn CurrentFilterFunction="GreaterThan" CurrentFilterValue="2.5"
  AndCurrentFilterFunction="LessThan" AndCurrentFilterValue="5.0" DataField="Freight"
  DataType="System.Decimal" HeaderText="Freight" SortExpression="Freight" UniqueName="Freight">
</telerik:GridBoundColumn>

In spite of having been created to allow for filtering the grid on two conditions, the new menu will give the freedom to set only one of those. The condition for which no data has been set will be ignored and RadGrid will filter its data only on the one for which a filter function and a filter value have been set. The filtering menu remains independent for each column - this means that the filtering menu options vary by the column's DataType and the properties of the special controls will depend on any other specific column properties such as Mask, DecimalDegits, PickerType etc.

The new filter menu can be used along-side the classic one. In this case, the GridTableView.IsFilterItemExpanded property should be set to true (the default value). When the two filter menus are switched on simultaneously, the data set for the first filter condition of the header context filter menu will be also set as filter data for the classic one and vice versa. If you want to use just the header context filter menu, then just set GridTableView.IsFilterItemExpanded property to false leaving, as mentioned above, the RadGrid.GridTableView/GridTableView.AllowFilteringByColumn property to true.

For more information on RadGrid header filtering menu, refer to this blog post and see the live example here.

Using HeaderContextMenu for showing column aggregates

From Q3 2010 on, RadGrid also enables showing column aggregates by using the HeaderContextMenu. You can turn the Aggregates submenu on and off by using the RadGrid.EnableHeaderContextAggregatesMenu / GridTableView.RadGrid.EnableHeaderContextAggregatesMenu property. This would be meaningful only if RadGrid.EnableHeaderContextMenu / GridTableView.EnableHeaderContextMenu is set to true.

The Aggregates menu will show the applicable aggregates for the current column, thus offering the user a choice which one to view. Apart from the ready to use aggregates, the menu also exposes an option for a custom one, which can be handled manually. You can declare your own aggregates in the column definitions and yet use the HeaderContextAggregatesMenu, as it will overwrite the aggregate shown in the footer.

Note that in order to be able to show the aggregates, you need to have ShowFooter property of RadGrid / the respective GridTableView, or ShowGroupFooter (when grouping is enabled) set to true.

Add items to HeaderContextMenu in order to set DataFormatString for the columns

You can modify the header context menu by add new items to the menu. To accomplish this task you need to reference RadGrid's HeaderContextMenu in the PreRenderComplete event handler. Thus you will be able to modify the Items collection of RadMenu. To add an item, you should create a new RadMenuItem instance and include it in the RadMenu's Items collection. The important point here is to add two attributes - "TableID" and "ColumnName". Those properties are required because on postback the grid retrieves the sent values in order to set new string format for the respective column (determined by the value of the ColumnName attribute)

Here is a code snippet illustrating the approach depicted above:

As you may noticed from this point you need to assign the correct values for the newly added attributes. This is done with the BuildColumnsMenu() method. Below is a code excerpt which demonstrates how to do that:

With this implementation you will also need to wire the HeaderContextMenu.ItemClick event as follows:

Finally, we need to wire the OnHeaderShowing client event. In its event handler you need to hide all items which are not related with the visible columns. The following code snippet shows how to achieve this:

Localize HeaderContextMenu items

In some cases you might want to set custom texts for the grid HeaderContextMenu items. For that purpose you can handle the menu ItemCreated event as below: