Showing posts with label Telerik. Show all posts
Showing posts with label Telerik. Show all posts

Tuesday, September 15, 2009

Telerik + Nettiers series

Radgrid paging, sorting, grouping and sorting with Nettiers objectdatasource

This post starts a new serie of post to demostrate the combination of two cools asp.net tools: Telerik Suite & Nettiers
This example shows the use of the more common features of Radgrid as paging, sorting, filtering and grouping with a Nettiers object datasource.
Some helpfull notes:
1) The objectdatasource method used to retrieve the data is GetPaged.
2) The code in OnSelecting event of the object datasource set correct the parameters for the objectdatasource.
3) The EnableLinqExpressions of radgrid is set to false to avoid by pass the objectdatasource results.
4) The CanRetrieveAllData of mastertableview is set to false in order to get a correct sorting.



The aspx page

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Radgrid.aspx.cs" Inherits="Radgrid" %>

<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<telerik:RadScriptManager ID="RadScriptManager1" runat="server">
</telerik:RadScriptManager>
<div>
<telerik:RadGrid ID="RadGrid1" ShowGroupPanel="True" GridLines="None" DataSourceID="EmployeeDataSource1"
AllowFilteringByColumn="True" AllowAutomaticDeletes="True" AllowAutomaticUpdates="True"
AllowAutomaticInserts="True" OnPreRender="RadGrid1_PreRender" AllowPaging="True"
AllowSorting="True" Skin="WebBlue" PageSize="10" EnableLinqExpressions="false"
AllowCustomPaging="true" runat="server">
<MasterTableView GroupLoadMode="client" AllowMultiColumnSorting="true" CommandItemDisplay="TopAndBottom"
DataSourceID="EmployeeDataSource1" DataKeyNames="EmployeeId" CanRetrieveAllData="false"
AllowCustomSorting="true">
<PagerStyle AlwaysVisible="true" />
</MasterTableView>
<ClientSettings AllowDragToGroup="True" AllowColumnsReorder="True" ReorderColumnsOnClient="True">
<Selecting AllowRowSelect="True" />
</ClientSettings>
</telerik:RadGrid>
<data:EmployeeDataSource ID="EmployeeDataSource1" runat="server" EnablePaging="True"
EnableSorting="True" SelectMethod="GetPaged" EnableCaching="false" OnSelecting="EmployeeDataSource1_OnSelecting">
</data:EmployeeDataSource>
</div>
</form>
</body>
</html>


The code behind

using System;
using System.Web.UI.WebControls;

public partial class Radgrid : System.Web.UI.Page
{
string masterTableFilter = string.Empty;

protected void Page_Load(object sender, EventArgs e)
{

}

protected void EmployeeDataSource1_OnSelecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
// Set the pagesize in each selecting to avoid the Int32.MaxValue (2147483647) passed by some Radgrid versions when filtering
e.Arguments.MaximumRows = RadGrid1.PageSize;

// Clear the master table filterExpression
if (!string.IsNullOrEmpty(RadGrid1.MasterTableView.FilterExpression))
{
masterTableFilter = RadGrid1.MasterTableView.FilterExpression;
RadGrid1.MasterTableView.FilterExpression = string.Empty;
}

// Set the Nettiers Datasource parameters
e.InputParameters["WhereClause"] = masterTableFilter;
e.InputParameters["OrderBy"] = RadGrid1.MasterTableView.SortExpressions.GetSortString();
}

// Restore the master table filterExpression
protected void RadGrid1_PreRender(object sender, EventArgs e)
{
RadGrid1.MasterTableView.FilterExpression = masterTableFilter;
}
}

Sunday, April 20, 2008

Telerik Radgrid: showing hierarchical data using a Dataset with multiple tables example

The telerik radgrid is one of the most complete grid control in the market. Have a cool set of features and covers the most commonly scenaries.
A common UI requirement is show Hierarchycal data, this data can be loaded in several ways with or without postbacks changing the property "HierarchyLoadMode". In case that the set of data to show is not great (use your criteria), you can choose load all data in the client obtaining a more responsive UI. To minimize roundtrips to database a good choice is code an stored procedure that returns multiple results and obtain a DataSet with multiple tables.
I make an example based on the AdventureWorks db to show the Departments and their respective employees.

The Stored Procedure:
This SP gets the data from Departments and Employees returning two results that share one column (DepartmentId) to make the parent/child relation.

CREATE PROCEDURE [HumanResources].[Department_Get_DepartmentAndEmployees]
AS

/* Get the departments */
SELECT HRD.DepartmentID, HRD.Name as DepartmentName
FROM HumanResournces.Department HRD
ORDER BY DepartmentName

/* Get the employees */
SELECT PC.FirstName,
PC.LastName,
HRE.Title,
HRDep.DepartmentId
FROM
HumanResources.Employee HRE
INNER JOIN Person.Contact PC ON PC.ContactId = HRE.ContactId
INNER JOIN HumanResources.EmployeeDepartmentHistory HRDep ON HRDep.EmployeeId = HRE.EmployeeId


The .aspx Code:
Note the ParentTableRelation tag uses the DepartmentId field to make the relation from the Employees table to the Department table.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Telerik Radgrid: showing hierarchical data using a Dataset with multiple tables</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="Scriptmanager1" runat="server">
</asp:ScriptManager>
<telerik:RadGrid ID="gvEmployeesByDepartment" runat="server" Width="95%" AutoGenerateColumns="False"
GridLines="None" ShowHeader="True" Skin="Web20">
<MasterTableView DataMember="Departments" DataKeyNames="DepartmentId" Width="100%"
Name="Customers" HierarchyLoadMode="Client">
<DetailTables>
<telerik:GridTableView DataMember="Employees" DataKeyNames="DepartmentId" Width="100%"
runat="server" ShowHeader="true">
<ParentTableRelation>
<telerik:GridRelationFields DetailKeyField="DepartmentId" MasterKeyField="DepartmentId" />
</ParentTableRelation>
<RowIndicatorColumn CurrentFilterFunction="NoFilter" FilterListOptions="VaryByDataType"
Visible="False">
<HeaderStyle Width="20px"></HeaderStyle>
</RowIndicatorColumn>
<ExpandCollapseColumn CurrentFilterFunction="NoFilter" FilterListOptions="VaryByDataType"
Visible="False" Resizable="False">
<HeaderStyle Width="20px"></HeaderStyle>
</ExpandCollapseColumn>
<Columns>
<telerik:GridBoundColumn DataField="Title" UniqueName="Title" ReadOnly="true" HeaderText="Title">
</telerik:GridBoundColumn>
<telerik:GridBoundColumn DataField="FirstName" UniqueName="FirstName" ReadOnly="true"
HeaderText="First Name">
</telerik:GridBoundColumn>
<telerik:GridBoundColumn DataField="LastName" UniqueName="LastName" ReadOnly="true"
HeaderText="Last Name">
</telerik:GridBoundColumn>
</Columns>
</telerik:GridTableView>
</DetailTables>
<RowIndicatorColumn CurrentFilterFunction="NoFilter" FilterListOptions="VaryByDataType"
Visible="False">
<HeaderStyle Width="20px"></HeaderStyle>
</RowIndicatorColumn>
<ExpandCollapseColumn CurrentFilterFunction="NoFilter" FilterListOptions="VaryByDataType"
Resizable="False">
<HeaderStyle Width="20px"></HeaderStyle>
</ExpandCollapseColumn>
<Columns>
<telerik:GridBoundColumn DataField="DepartmentName" UniqueName="DepartmentName" HeaderText="Department">
</telerik:GridBoundColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
</form>
</body>
</html>


The .cs Code:

using System;
using System.Data;
using System.Web.UI;
using System.Data.SqlClient;

public partial class _Default :System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
BindDepartmentsAndEmployees();
}

private void BindDepartmentsAndEmployees()
{
SqlConnection conn = new SqlConnection(@"Integrated Security=SSPI;Persist Security Info=False;User ID=marketpoint;Initial Catalog=AdventureWorks;Data Source=(local)\sqlexpress");
SqlCommand cmd = new SqlCommand("[HumanResources].[Department_Get_DepartmentAndEmployees]", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet dsDepartmentAndEmployees = new DataSet();
da.Fill(dsDepartmentAndEmployees);
if(da != null)
{
// Renames Dataset table to get more clear names in grid declarative properties
dsDepartmentAndEmployees.Tables[0].TableName = "Departments";
dsDepartmentAndEmployees.Tables[1].TableName = "Employees";
gvEmployeesByDepartment.DataSource = dsDepartmentAndEmployees;
gvEmployeesByDepartment.DataBind();
}
}
}

The UI Result (Click to Enlarge):

Monday, December 3, 2007

NetTiers "SELECT DISTINCT" method

Using Nettiers CRUD methods and custom methods we get a very complete DAL that covers a wide range of the queries needed by a application. A frequently question in forums is about how obtain a "Select Distinct" clause equivalent in Nettiers. I've developed a method to obtain the distinct entities based on the values of one or more properties.

public static TList<T> SelectDistinctFromList<T>(TList<T> originalList, System.Enum[] distinctProperties) where T : IEntity, new()
{
Type instanceType = originalList.GetType().GetGenericArguments()[0].BaseType;

PropertyInfo[] propertyColumns = new PropertyInfo[distinctProperties.Length];
for(int i = 0; i < distinctProperties.Length; i++)
{
propertyColumns[i] = instanceType.GetProperty(distinctProperties[i].ToString());
}

TList<T> resultList = new TList<T>();
System.Collections.Specialized.StringCollection keys = new System.Collections.Specialized.StringCollection();
foreach (T instance in originalList)
{
string key = string.Empty;
foreach (PropertyInfo pi in propertyColumns)
{
key += pi.GetValue(instance, null) + "|";
}
if (!keys.Contains(key))
{
keys.Add(key);
resultList.Add(instance);
}
}
return resultList;
}

As you can see there are two steps to get the "Select Distinct", in the first step is retrieve the base collection (TList) and in the second step apply the SelectDistinctFromList method.
This approach is adequate when the first step data is cached, have not a big collection or want to do many "Select Distinct" over the collection. For example, using a Nettiers project generated from
the AdventureWorks DB first obtains the orders for a SalesPerson and after get a list of orders with the distinct Territories and other list with the distinct Customers and Status.

SalesOrderHeaderService service = new SalesOrderHeaderService();
TList<SalesOrderHeader> orders = service.GetBySalesPersonId(279);

TList<SalesOrderHeader> distinctTerritoriesFromOrders = SelectDistinctFromList<SalesOrderHeader>(orders, new Enum[] { SalesOrderHeaderColumn.TerritoryId });

TList<SalesOrderHeader> distinctCustomerAndStatusFromOrders = SelectDistinctFromList<SalesOrderHeader>(orders, new Enum[] { SalesOrderHeaderColumn.CustomerId, SalesOrderHeaderColumn.Status });