Best way to pass a numeric value from one ASP.NET user control to another without using QueryString

  • Thread starter Thread starter Ken Fine
  • Start date Start date
K

Ken Fine

I've made two user controls that are intended to be a generalized solution
for listing content, and managing classes of content in a master/detail
arrangement. I've put both of these on a single webpage and mediated the
views with a MultiView.

One user control is an overview page that lists items in a ListView. Users
select items that have a unique ID attached to them.

The second user control is a detail/edit view that shows a single record.

In my first version of this, I had the overview page pass the ID via a
querystring. I would prefer to have that ID hidden, so my next idea was to
assign the selected ID value to a session variable in the
ListView1_ItemCommand event, and have the detail page try to consume the ID.
For anyone who has tried this, you know this will lead to problems due to
page lifecycle issues (see analogous issue here:
http://forums.asp.net/t/1306495.aspx ). I am aware there is a somewhat
non-intuitive workaround as described in the message thread.

I think I'm thinking about this too much, and there is probably a
better/simpler way to get a numeric value from the ListView in user control
A to user control B than using Sessions. Can someone unbend my brain and
suggest a solution?

Thank you
-KF
 
Somebody else online pointed me to delegates as a solution for this kind of
a communication issue between decoupled controls. However, something's still
off in my syntax: I am sure I am making a newbie error.

Assume the following:
AdminGeneralOverview.ascx, a user control for displaying an overview of
content in the context of a ListView and allowing the selection of items
AdminGeneralContentItem.ascx, a user control for displaying a detail view of
content
combination.aspx, which combines the two controls above.

I have this code in the class declaration of AdminGeneralOverview.ascx.cs

public delegate void PassID(string ID);
public event PassID PassIDEvent;

I have this code set up on the ListView's Item_Command. This might be all
wrong:
protected void ListView1_ItemCommand(object sender,
ListViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "PassItemId":
if (PassIDEvent != null)
{
PassIDEvent(e.CommandArgument.ToString());
}
break;
}
}

Outside of the page load function in AdminGeneralContentItem.cs I have a
public "LoadItemID" function set up that assigns an ID to the User Control's
ID property:

public void LoadItemID(int contentId)
{
this.ContentID = contentId;
}

In combination.aspx.cs, I have this set up in the Page_Load method:
this.AdminGeneralOverview1.PassIDEvent += new
AdminGeneralOverview1.PassID(LoadItemID);

This last item is syntactically wrong, but I don't know how. The second
listing of "AdminGeneralOverview1", after the += operator, has red sqiggles
under it and the following error message: "Type or namespacename expected,
but field name found"

I have secondary question associated with this beyond the syntax problems.
On combination.aspx, I am using a MultiView to change between the master
view and the detail view. I would like to be able to somehow detect when the
delegate has been called, so that combination.aspx will know to switch from
the content overview displayed by AdminGeneralOverview.ascx to the detail
view displayed by AdminGeneralContentItem.ascx. Is there any easy way to do
this?

Thank you in advance.

-KF
 
Hi Ken,

My name is Allen Chen. It's my pleasure to work with you on this issue.

From your description I think your requirement is to share a value between
two Web User Controls. Is my understanding correct?

If so please try following steps. It will create a demo project that
demonstrates how to do this.

1. Create an ASP.NET Web Project in Visual Studio 2008
2. Add two Web User Controls in this project. Name them as WebUserControlA
and WebUserControlB.
3. Paste following code in WebUserControlA.ascx:

<%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="WebUserControlA.ascx.cs"
Inherits="WebApplication6.WebUserControlA" %>
WebUserControlA
<asp:Button ID="Button1" runat="server" Text="Get Value from
WebUserControlB"
onclick="Button1_Click" />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>

4. Paste following code in WebUserControlA.ascx.cs:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace WebApplication6
{
public partial class WebUserControlA : System.Web.UI.UserControl
{

protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
public string WebUserControlB_ID
{
get;
set;
}
protected override object SaveControlState()
{
return WebUserControlB_ID;
}

protected override void LoadControlState(object state)
{
if (state != null)
{
WebUserControlB_ID = (string)state;
}
}

protected void Button1_Click(object sender, EventArgs e)
{
if (this.Parent == null) {
throw new Exception("This UserControl must be put in a
Container!");
}
else if (WebUserControlB_ID != null)
{
WebUserControlB wb =
this.Parent.FindControl(WebUserControlB_ID) as WebUserControlB;
if (wb != null)
{
this.Label1.Text = "Value is: " + wb.SharedValue;
}
}
}
}
}
5. Paste following code in WebUserControlB.ascx:
<%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="WebUserControlB.ascx.cs"
Inherits="WebApplication6.WebUserControlB" %>
WebUserControlB
<br />
Input Value: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />

<asp:Button ID="Button1"
runat="server" Text="Save Value" onclick="Button1_Click" />

6. Paste following code in WebUserControlB.ascx.cs:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace WebApplication6
{
public partial class WebUserControlB : System.Web.UI.UserControl
{
public string SharedValue { get; set; }
protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
protected override object SaveControlState()
{
return SharedValue;
}

protected override void LoadControlState(object state)
{
if (state != null)
{
SharedValue = (string)state;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
this.SharedValue = this.TextBox1.Text;

}
}
}

7. Paste following code in Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication6._Default" %>

<%@ Register src="WebUserControlA.ascx" tagname="WebUserControlA"
tagprefix="uc1" %>
<%@ Register src="WebUserControlB.ascx" tagname="WebUserControlB"
tagprefix="uc2" %>

<!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>Untitled Page</title>

</head>
<body>
<form id="form1" runat="server">
<div>

<asp:Button id="Button1" runat="server" Text="View1"
OnClick="Button1_Click" /> &nbsp;
<asp:Button id="Button2" runat="server" Text="View2"
OnClick="Button2_Click" /> &nbsp;

<br /><br />

<asp:MultiView id="MultiView1" runat="server" ActiveViewIndex=0>
<asp:View id="View1" runat="server">
<uc1:WebUserControlA ID="WebUserControlA1"
runat="server" WebUserControlB_ID="WebUserControlB1" />
</asp:View>
<asp:View id="View2" runat="server">
<uc2:WebUserControlB ID="WebUserControlB1"
runat="server" />
</asp:View>
</asp:MultiView>



</div>
</form>
</body>
</html>

8. Paste following code in Default.aspx.cs:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;

namespace WebApplication6
{
public partial class _Default : System.Web.UI.Page
{

protected void Button1_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View1);
}

protected void Button2_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View2);
}


}
}
9. Set Default.aspx as the start page. Start debugging.
10. Click "View2" button to view the WebUserControlB. Input some value.
Click the "Save" button.
11. Click "View1" button to back to the WebUserControlA. Click the "Get
Value from WebUserControlB" button to retrieve data from WebUserControlB.
The data will be displayed below this button.


To explain the code:

The shared data is exposed via a property in WebUserControlB and stored via
the control state. Thus it can be maintained after postback. Please refer
to the following article to learn more about the SaveControlState/
LoadControlState method.
http://msdn.microsoft.com/en-us/library/system.web.ui.control.savecontrolsta
te.aspx

We need to provide the ID of the WebUserControlB for the WebUserControlA to
get the reference of the WebUserControlB via FindControl method and then
get the shared data.

Please have a try and let me know if it works. If you have further
questions please feel free to ask.

Regards,
Allen Chen
Microsoft Online Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Ken,

Do you have any progress on this issue?

Regards,
Allen Chen
Microsoft Online Support
 
Hi Ken,

Do you have any progress on this issue?

Regards,
Allen Chen
Microsoft Online Support

Allen,

You may have snowed the lad with your explanation. However, I
followed it and found it useful in my transit from VB to C#. Thanks.

Steve T.
 
Back
Top