Introduction
A developer in the forums is asking how to pass data that is coming from a WebUserControl
control to the main page. Basically, the scenario is that, he has a WebUserControl
which contains a GridView
that is wrapped around inside an ASPNET Ajax UpdatePanel
control. The WebUserControl
will then be used in the page (ContentPage
) that is hosted within a MasterPage
. The page contains some TextBox
in which it will be populated once the user selects a row from the GridView
, also the ModalPopup
is defined within that page.
The question is quite interesting, and so I’ve give it a shot and created a simple demo. Here’s the solution that I came up with and provide it to the developer.
The Page Markup
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="Modal.aspx.cs" Inherits="WebAppDemo.Modal" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<%@ Register src="UserControl/WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
<style type="text/css">
.modal-bg{
background-color:Gray;
filter:alpha(opacity=50);
opacity:0.6;
z-index:999;
}
.modal{
position:absolute;
}
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<asp:TextBox ID="txtProductName" runat="server" />
<asp:TextBox ID="txtPrice" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server" Text="Show" />
<asp:Panel ID="pnlPopUp" runat="server"
style="display:none" CssClass="modal" >
<uc1:WebUserControl1 ID="WebUserControl11" runat="server" />
</asp:Panel>
<asp:ModalPopupExtender ID="ModalPopupExtender1" runat="server"
TargetControlID="LinkButton1"
PopupControlID="pnlPopUp"
BackgroundCssClass="modal-bg">
</asp:ModalPopupExtender>
</asp:Content>
There’s nothing really fancy about the markup above. It just contains two TextBox
, a ModalPopup
, a LinkButton
as the target control for the Modal, and a Panel
control that contains the WebUserControl
.
You may also have noticed that I’ve created a simple CSS for the modal.
The WebUserControl Markup
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs"
Inherits="WebAppDemo.UserControl.WebUserControl1" %>
<%@ Register Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="ID" />
<asp:BoundField DataField="ProductName" HeaderText="Product Name"/>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="txtPrice" runat="server"
Text='<%# Eval("Price") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="txtAmount" runat="server"
Text="<%# Eval("Amount") %>" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="Button1" runat="server"
Text="Select" onclick="Button1_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="GridView1" />
</Triggers>
</asp:UpdatePanel>
The WebUserControl
is where we defined the GridView
. Noticed that the GridView
is wrapped within an UpdatePanel
control. We then set the ID of GridView
as the PostbackTrgigger
for the UpdatePanel
to trigger the control events within GridView
– in this case, the Click
event of the Button
control.
Code Behind
Now, here's the code behind for the WebUserControl
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using AjaxControlToolkit;
namespace WebAppDemo.UserControl
{
public partial class WebUserControl1 : System.Web.UI.UserControl
{
private DataTable GetSampleData()
{
DataTable dt = new DataTable();
DataRow dr = null;
dt.Columns.Add(new DataColumn("ID", typeof(string)));
dt.Columns.Add(new DataColumn("ProductName", typeof(string)));
dt.Columns.Add(new DataColumn("Price", typeof(string)));
dt.Columns.Add(new DataColumn("Amount", typeof(string)));
dr = dt.NewRow();
dr["ID"] = 1;
dr["ProductName"] = "Galaxy S";
dr["Price"] = "100";
dr["Amount"] = "10";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = 2;
dr["ProductName"] = "iPhone 4";
dr["Price"] = "200";
dr["Amount"] = "2";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = 3;
dr["ProductName"] = "HTC Mobile";
dr["Price"] = "50";
dr["Amount"] = "10";
dt.Rows.Add(dr);
return dt;
}
private void BindGrid(DataTable source)
{
GridView1.DataSource = source;
GridView1.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
BindGrid(GetSampleData());
}
protected void Button1_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
GridViewRow gvRow = (GridViewRow)b.NamingContainer;
string productName = gvRow.Cells[1].Text;
string price = ((TextBox)gvRow.FindControl("txtPrice")).Text;
Type thePage = Page.GetType();
System.Reflection.PropertyInfo[] pi = thePage.GetProperties();
foreach (System.Reflection.PropertyInfo pinfo in pi)
{
if (pinfo.Name == "ProductName")
{
pinfo.SetValue(Page, productName, null);
}
else if (pinfo.Name == "Price")
{
pinfo.SetValue(Page, price, null);
}
}
((ModalPopupExtender)this.Parent.Parent.FindControl
("ModalPopupExtender1")).Hide();
}
}
}
You may noticed that I just used a fake data as the data source for GridView
. At the Button
’ s Click
event, I have used reflection to access the property metadata. I then used the SetValue to populate the controls in the main page based on the selected row values from the GridView
. Keep in mind that you can also use the FindControl() method to reference a control and assign a value, but I opt to use reflection in this particular demo because i just want to pass data, and I don’t want to deal with naming containers to find specific controls in the page. FindControl
method is useful when you want to manipulate the control, like for example changing the Width
or perhaps toggling the Enabled
or Visible
property of the control.
You can also use properties if you want to get the value from a UserControl in the main page. For example you expose a public property within your WebUserControl
, then in your main page, you simply reference the property defined in your WebUserControl
, for example at Button’s click event. Though using properties isn’t applicable for this particular scenario, since we are passing data to the main page right after selecting a row and not getting data.
Output
Running the page will display something like this:
After clicking the “Show” link:
After selecting a row from GridView
:
That’s it! I hope someone finds this post useful.