Common_PostbackManager_CSharp\PostbackManagerWebSite\GetAttributeTable.aspx.cs
// Copyright 2010 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // public partial class GetAttributeTable : System.Web.UI.Page { #region Page Member Variables // Whether attributes are to be retrieved for the clicked layer private bool _getLayerAttributes = false; // The number of records displayed at one time on the attribute table private int _pageSize = 20; #endregion #region ASP.NET Page Life Cycle Event Handlers - Page_Load // Wires event handlers protected void Page_Load(object sender, System.EventArgs e) { PostbackManager1.RequestReceived += new PostbackManager_CSharp.RequestReceivedEventHandler(PostbackManager1_RequestReceived); Toc1.NodeClicked += new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeClickedEventHandler(Toc1_NodeClicked); Toc1.NodesPopulated += new System.EventHandler(Toc1_NodesPopulated); } #endregion #region Web ADF Control Event Handlers - Toc1_NodesPopulated, Toc1_NodeClicked // Fires once the TOC's nodes have been initialized void Toc1_NodesPopulated(object sender, System.EventArgs e) { // Find which nodes correspond to a layer and mark them with an HTML attribute foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node in Toc1.Nodes) this.MarkLayerNodes(node); } // Fires when a TOC node is clicked void Toc1_NodeClicked(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs args) { // Check whether layer attributes are to be retrieved. This value is set in // PostbackManager1_RequestReceived if (!_getLayerAttributes) return; // Get the TocLayer corresponding to the clicked node ESRI.ArcGIS.ADF.Web.TocLayer selectedLayer = args.Node.Data as ESRI.ArcGIS.ADF.Web.TocLayer; // Get the data frame node that contains the layer node ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode dataFrameNode = this.GetParentDataFrameNode(args.Node); // Create a data table containing the clicked layer's attributes System.Data.DataTable attributeTable = this.GetLayerAttributeData(Map1, dataFrameNode.Text, selectedLayer.ID); // Apply the layer's LayerFormat to the attribute table. This will set properties such as field // visibilities and display names. ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat layerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(MapResourceManager1, dataFrameNode.Text, selectedLayer.ID); layerFormat.Apply(attributeTable); // Store the table in session for quick retrieval during paging or sorting this.Session["AttributeTable"] = attributeTable; // Calculate the number of pages the displayed table will have and store the number in session int pageCount = (int)System.Math.Round(((double)attributeTable.Rows.Count / (double)_pageSize) + .5); this.Session["PageCount"] = pageCount; // Display the table's first page this.ShowAttributeTable(1); // Copy the callback results of the floating panel containing the table to the TOC so the // results that will display the table are processed on the client. Toc1.CallbackResults.CopyFrom(FloatingPanel1.CallbackResults); // Pass the name of the clicked layer back to the client via PostbackManager's CustomResults property. // This will be used to update the floating panel's title. PostbackManager1.CustomResults = args.Node.Text; } #endregion #region Custom Control Event Handlers - PostbackManager1_RequestReceived void PostbackManager1_RequestReceived(object sender, PostbackManager_CSharp.AdfRequestEventArgs args) { // Get the request's arguments and extract EventArg System.Collections.Specialized.NameValueCollection requestArgs = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.ParseStringIntoNameValueCollection(args.RequestArguments, true); string eventArg = requestArgs["EventArg"]; // Check whether the request was initiated by the TOC if (args.CallingControl.ID == Toc1.ID) { // Check whether the request includes the custom argument indicating that layer attributes are to be // retrieved. This argument is added to the request on the client via onAdfRequest, which is a handler for // the PostbackManager's client-side invokingRequest event. if (requestArgs["getAttributes"] != null) _getLayerAttributes = true; } // Check whether the request was initiated by paging or sorting the attribute table else if (eventArg == "nextPage" || eventArg=="previousPage" || eventArg=="firstPage" || eventArg=="lastPage" || eventArg=="sort") { // Get the current page number int pageNumber = (int)this.Session["PageNumber"]; switch (eventArg) { // Set the page number if the request is for paging. If it is for sorting, call the SortAttributeTable method case "nextPage" : pageNumber++; break; case "previousPage" : pageNumber--; break; case "firstPage" : pageNumber = 1; break; case "lastPage" : pageNumber = (int)this.Session["PageCount"]; break; case "sort" : this.SortAttributeTable(requestArgs["Column"]); break; } // Update the displayed table to show the specified page this.ShowAttributeTable(pageNumber); // Copy the callback results of the floating panel containing the attribute table to the PostbackManager so the // updates to the table display are processed on the client. PostbackManager1.CallbackResults.CopyFrom(FloatingPanel1.CallbackResults); } } #endregion #region Private Page Methods #region TOC Node Manipulation - MarkLayerNodes, GetParentDataFrameNode // Finds TOC layer nodes that are descendants of the passed-in node and adds an HTML attribute to // them marking them as such private void MarkLayerNodes(ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node) { // Check whether the passed-in node is a layer node and add an "IsLayer" attribute to it if so if (node.Data is ESRI.ArcGIS.ADF.Web.TocLayer) node.Attributes.Add("IsLayer", "true"); // Recursively call the method on the passed-in node's child nodes foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode childNode in node.Nodes) this.MarkLayerNodes(childNode); } // Retrieves the TOC data frame node that is an ancestor of the passed-in node private ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode GetParentDataFrameNode( ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node) { // Declare a node variable to hold the function's return value ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode dataFrameNode = null; // If the current node is a data frame node, store it in the return variable. Otherwise, call the // method recursively on the node's parent. if (node.Data is ESRI.ArcGIS.ADF.Web.TocDataFrame) dataFrameNode = node; else dataFrameNode = this.GetParentDataFrameNode(node.Parent as ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode); return dataFrameNode; } #endregion #region Attribute Table Manipulation - ShowAttributeTable, PopulateAttributeTable, SortAttributeTable // Updates the AttributeTable control to display attributes on the specified page of the current layer private void ShowAttributeTable(int pageNumber) { // Retrieve the number of attribute pages and validate the requested page number int pageCount = (int)this.Session["PageCount"]; if (pageNumber == 0 || pageNumber > pageCount) return; // Update the current page number this.Session["PageNumber"] = pageNumber; // Get the attribute DataTable for the current layer System.Data.DataTable attributeTable = this.Session["AttributeTable"] as System.Data.DataTable; // Calculate the first and last indexes of the rows to be displayed int startIndex = (pageNumber - 1) * _pageSize; int stopIndex = (pageNumber * _pageSize) - 1; if (stopIndex >= attributeTable.Rows.Count) stopIndex = attributeTable.Rows.Count - 1; // Update the attribute table display this.PopulateAttributeTable(attributeTable, startIndex, stopIndex); // Update the paging text PageLabel.Text = string.Format("Current Page: {0} of {1}", pageNumber, pageCount); // Make sure the floating panel containing the attribute table is visible, then refresh it to // apply the updates to the attribute table control FloatingPanel1.ShowFloatingPanel(); FloatingPanel1.Refresh(); } // Displays the data specified by the method parameters on the AttributeTable control private void PopulateAttributeTable(System.Data.DataTable dataTable, int startIndex, int stopIndex) { // Remove all rows from the display table AttributeTable.Rows.Clear(); AttributeTable.GridLines = System.Web.UI.WebControls.GridLines.Both; // Create a row for the header row and add it to the display table System.Web.UI.WebControls.TableRow row = new System.Web.UI.WebControls.TableRow(); AttributeTable.Rows.Add(row); System.Web.UI.WebControls.TableCell cell = null; // Add the name of each visible field to the header row foreach (System.Data.DataColumn column in dataTable.Columns) { // Check whether the current column is visible if (System.Convert.ToBoolean(column.ExtendedProperties[ESRI.ArcGIS.ADF.Web.Constants.ADFVisibility])) { // Create a cell for the column header and apply a bold font to it cell = new System.Web.UI.WebControls.TableCell(); cell.Font.Bold = true; // Set the header text to either the field's display name or its database name if a display name is // not specified string headerText = (string.IsNullOrEmpty(column.Caption)) ? column.ColumnName : column.Caption; // Create a hyperlink for the header - we do this to make the table sortable by clicking a header cell System.Web.UI.HtmlControls.HtmlAnchor sortLink = new System.Web.UI.HtmlControls.HtmlAnchor(); sortLink.InnerText = headerText; // Set the header link to issue an asynchronous request to the server via PostbackManager's doAsyncRequest sortLink.HRef = string.Format( "javascript:ESRI.ADF.Samples.PostbackManager.doAsyncRequest('EventArg=sort&Column={0}');", headerText); cell.Controls.Add(sortLink); row.Cells.Add(cell); } } // Add the data rows to the display table for (int i = startIndex; i <= stopIndex; i++) { // Add a row to the display table row = new System.Web.UI.WebControls.TableRow(); AttributeTable.Rows.Add(row); // Get the current row from the data table System.Data.DataRow dataRow = dataTable.Rows[i]; // Add a new cell for each visible column and populate it with that column's value foreach (System.Data.DataColumn column in dataTable.Columns) { // Check whether the current field is visible if (System.Convert.ToBoolean(column.ExtendedProperties[ESRI.ArcGIS.ADF.Web.Constants.ADFVisibility])) { // Set the cell's text to be the value of the current column in the current row cell = new System.Web.UI.WebControls.TableCell(); cell.Text = System.Convert.ToString(dataRow[column.ColumnName]).Trim(); // Set a tab as the cell's text if there is no current value. Without this, the cell borders do // not render in this situation. if (string.IsNullOrEmpty(cell.Text)) cell.Text = " "; row.Cells.Add(cell); } } } } // Sorts the display table on the specified column private void SortAttributeTable(string columnName) { // Get the current data table from session System.Data.DataTable attributeTable = this.Session["AttributeTable"] as System.Data.DataTable; // If the column has a display name specified, retrieve the database field name if (!attributeTable.Columns.Contains(columnName)) { foreach (System.Data.DataColumn column in attributeTable.Columns) { if (column.Caption == columnName) { columnName = column.ColumnName; break; } } } // Get the current sort direction string currentSort = this.Session["CurrentSort"] as string; // Create a sort expression that will sort on the passed-in column in the opposite // direction of the current sort string sortExpression = (currentSort == string.Format("{0} ASC", columnName)) ? string.Format("{0} DESC", columnName) : string.Format("{0} ASC", columnName); // Update the current sort expression stored in session this.Session["CurrentSort"] = sortExpression; // Apply the sort attributeTable.DefaultView.Sort = sortExpression; // Replace the current data table with the sorted table this.Session["AttributeTable"] = attributeTable.DefaultView.ToTable(); } #endregion // Retrieves attribute data for the specified layer private System.Data.DataTable GetLayerAttributeData(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap, string resourceName, string layerID) { // Get the map functionality for the resource ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mapFunctionality = adfMap.GetFunctionality(resourceName); // Get the resource and make sure it supports querying ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = mapFunctionality.Resource; bool supportsQueries = gisResource.SupportsFunctionality (typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)); if (!supportsQueries) return null; // Get query functionality for the resource ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality = gisResource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null) as ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality; // Initialize a query filter. We do not specify a where clause so all features are returned. // We also specify that geometry not be returned since only the attribute data will be used and // retrieving geometry is a relatively expensive operation. ESRI.ArcGIS.ADF.Web.QueryFilter adfQueryFilter = new ESRI.ArcGIS.ADF.Web.QueryFilter(); adfQueryFilter.ReturnADFGeometries = false; adfQueryFilter.MaxRecords = 10000; // Execute the query, returning the result return queryFunctionality.Query(mapFunctionality.Name, layerID, adfQueryFilter); } #endregion }