A common question I get when customers are working with data bound controls is:
How do I easily access the primary key [or any other piece of extra data] on the client, and still hide it from the user?
The concept lies in placing the “extra data” into a hidden container, associated by item index, for easy access on the client. Once you know the index of the selected item, you can query the page for the data that matches the selected index value.
The idea is the same whether or not you are using just about any type of data bound control. For this example I am using the WebDataGrid. I chose this control only because the grid is the control where this question most often comes up, but you could just as easily implement this approach with any other data bound control. This example also only represents one way to approach the problem – there are numerous other ways to accomplish the same goal. Hopefully this article will get you thinking in the right direction to build an implementation that best fits your needs.
If you would like, you can view a video of the example implemented in this article.
The code behind for this sample is very basic. When the page loads the grid is filled with a list of 10 instances of the Person object.
using System; using FizzWare.NBuilder; public partial class Default : System.Web.UI.Page { protected int indexer = 0; protected void Page_Load(object sender, EventArgs e) { if (!this.Page.IsPostBack) { this.wdg.DataSource = Builder<person>.CreateListOfSize(10).Build(); this.wdg.DataBind(); } } }</person>
Additionally I’ve added an indexer as a protected field to the page. This indexer will keep track of the item index as the control is being bound.
In this page I’ve added a WebDataGrid and a SPAN at the bottom of the page to report the value of the record’s primary key value.
For this example the “extra data” is the item’s primary key value, but you could just as easily have included any other additional data item. To generate the appropriate markup for the control a TemplateDataField is used to add in a hidden input field as part of the code generated for the control. The hidden input gets it’s unique id value from prefixing the id with some sort of sensible value and then concatenating the index value at the end. The data for the value attribute is emitted into the control just as you would under normal circumstances.
In order to save from having to write extra code in order to increment the indexer during data binding, the incrementing expression found on line 10 is used to keep the indexer’s value in sync with the controls current index.
<form id="form1" runat="server"> <asp:ScriptManager runat="server" /> <ig:WebDataGrid ID="wdg" EnableViewState="False" runat="server" AutoGenerateColumns="False"> <Columns> <ig:TemplateDataField Key="FirstName" Header-Text="First Name"> <ItemTemplate> <input type="hidden" id="pk<%= this.indexer %>" value="<%# Eval("Id") %>" /> <%# Eval("FirstName") %> <% this.indexer++; %> </ItemTemplate> </ig:TemplateDataField> <ig:BoundDataField DataFieldName="LastName" Header-Text="LastName" Key="LastName" /> <ig:BoundDataField DataFieldName="LastLoginDate" Header-Text="LastLoginDate" Key="LastLoginDate" /> </Columns> <Behaviors> <ig:RowSelectors> </ig:RowSelectors> <ig:Selection CellClickAction="Row" RowSelectType="Single"> <SelectionClientEvents RowSelectionChanged="onRowSelectionChanged" /> </ig:Selection> </Behaviors> </ig:WebDataGrid> <p>The selected primary key value is: <span id="selectedPK"></span></p> </form>
Finally the Selection behavior is customized to fire the RowSelectionChanged event. In this case the event is handled by a function named onRowSelectionChanged. The next section discusses the required JavaScript needed to complete the solution.
The script you implement may vary depending on what type of data bound control you are working with, but in this instance you need to look at the selected rows and work down in order to find the selected index. Once the index is known then pairing the correct prefix with the selected index value will give you direct access to any hidden data on the page.
<script type="text/javascript"> function onRowSelectionChanged(sender, eventArgs) { var rows = eventArgs.getSelectedRows(); var row = rows.getItem(0); var index = row.get_index(); $get("selectedPK").innerHTML = $get("pk" + index).value; } </script>