Web User Control to Web User Control...


Hi, I have 2 User controls on a page and want Control1 to call a method of Control2. Is this Possible?
Example:
Con1 = Datalist showing products, each with a Quantity Box and a Button.
Con2 = Repeater showing Cart Preview (name, Price)
in page.aspx.
When I click on the button on the DataList in Con1 it adds the item into the Session based Cart. However it does not update the Cart Preview. I need to call BindPreview() in Con2 in order to update the Cart Preview...
Does that make sense? argh! any help much appreciated!
Pete

Web Design Nottingham, UK
0
pete_m
1/4/2006 2:38:55 PM
📁 asp.net.web-forms
📃 93655 articles.
⭐ 6 followers.

💬 10 Replies
👁️‍🗨️ 2593 Views



Well I can call BindPreview() from my Control2 by using
cp1.BindPreview();
But I am getting a NullReferenceException error when calling the method from another control. Here is the code for the method:
public void BindPreview()
{
  objCartDT1 = (DataTable)Session["Cart"];
  RptCartPreview.DataSource = objCartDT1;
  RptCartPreview.DataBind();
}
I am getting the error on the first line.....any ideas? Cant seem to find this anywhere

Web Design Nottingham, UK
0
pete_m
1/4/2006 3:47:44 PM
Create an event in Control1 and handle the event in the page that contains the control.  From the page that contains the control you can then call your BindPreview for control2.

Example:
1.  Create 2 user controls named control1.ascx and control2.ascx.
2.  Create one page called WebForm1.aspx.
3.  Open control1.ascx and add a button named Button1.
4.  Open control1.ascx.cs and add the following code inside the control1 class:
        protected System.Web.UI.WebControls.Button Button1;
       // Define the event
        public event EventHandler BindControl2;
       // Notify the object registered object (EventHandler(ctrl1_BindControl2))
        protected virtual void OnBindControl2(System.EventArgs e)
        {
            if (BindControl2 != null)
            {
                BindControl2(this, e);
            }
        }
       // Raise the event
        private void Button1_Click(object sender, System.EventArgs e)
        {
            OnBindControl2(e);
        }
5.  Open control2.ascx.cs and add the following code inside the control2 class:
        public void BindPreview()
        {
            Response.Write("Bind Preview worked");
        }
6.  Open WebForm1.aspx and add both user controls to the page separated by breaks <br>.
7.  Open WebForm1.aspx.cs and add the following code to the WebForm1 class:
        protected control1 ctrl1;
        protected control2 ctrl2;
        private void Page_Load(object sender, System.EventArgs e)
        {
             // Register the event handler
            ctrl1.BindControl2 += new EventHandler(ctrl1_BindControl2);
        }
       // Define the eventhandler
        private void ctrl1_BindControl2(object sender, System.EventArgs e)
        {
            ctrl2.BindPreview();
        }
You are basically creating an event on your user control (control1) so that your container (WebForm1) can register the eventhandler with that event.  From WebForm1 you can access the second user control (control2) just as you do any other control (by reference) and execute it's public methods.
Hope this helps!

Paul
0
eccsolutions
1/4/2006 10:24:05 PM

Hi Paul, Thanks for the response,
You may have to bear with me Im afraid - I tried out the above (to the letter) and I'm getting a NullReferenceException on the line
 ctrl1.BindControl2 += new EventHandler(ctrl1_BindControl2);
in webform1. Any ideas...
Thanks again,
Pete

Web Design Nottingham, UK
0
pete_m
1/5/2006 9:51:57 AM
Paste the full error code.  Should not be getting that error.  Sounds like you forgot to place the usercontrols on WebForm1.aspx like so:

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="codetestsc.WebForm1" %>
<%@ Register TagPrefix="uc1" TagName="control1" Src="control1.ascx" %>
<%@ Register TagPrefix="uc1" TagName="control2" Src="control2.ascx" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    <HEAD>
        <title>WebForm1</title>
        <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
        <meta name="CODE_LANGUAGE" Content="C#">
        <meta name="vs_defaultClientScript" content="JavaScript">
        <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
    </HEAD>
    <body>
        <form id="Form1" method="post" runat="server">
            <uc1:control1 id="ctrl1" runat="server"></uc1:control1><br><br><br>
            <uc1:control2 id="ctrl2" runat="server"></uc1:control2>
        </form>
    </body>
</HTML>

Paul
0
eccsolutions
1/5/2006 2:32:05 PM

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
on the line: ctrl1.BindControl2 += new EventHandler(ctrl1_BindControl2);
 

Web Design Nottingham, UK
0
pete_m
1/5/2006 2:36:54 PM

oops! my fault - I had the Control IDs as "Control1" rather than "ctrl"
Thanks for the help - It's an extremely useful example  :)
Pete

Web Design Nottingham, UK
0
pete_m
1/5/2006 3:47:21 PM
Did you add the usercontrols to the WebForm1.aspx page with the ID's ctrl1 and ctrl2?  The error is telling me that the object reference ctrl1 is not set to an instance of an object.  Make sure you add the following to WebForm1.aspx:

Place these at the top of the page with your Page Directive:
<%@ Register TagPrefix="uc1" TagName="control1" Src="control1.ascx" %>
<%@ Register TagPrefix="uc1" TagName="control2" Src="control2.ascx" %>
Place these inbetween the <form> tags:
<uc1:control1 id="ctrl1" runat="server"></uc1:control1><br><br><br>
<uc1:control2 id="ctrl2" runat="server"></uc1:control2>

Paul
0
eccsolutions
1/5/2006 3:52:55 PM

I'm using VWD Express (C#) - and don't really know what I'm doing - but had to make the following changes (in bold) to Paul's example to get it to work:
1.  Create 2 user controls named control1.ascx and control2.ascx.
2.  Create one page called WebForm1.aspx.
3.  Open control1.ascx and add a button named Button1.
4.  Open control1.ascx.cs and add the following code inside the control1 class:
        protected System.Web.UI.WebControls.Button Button1;

       // Define the event
        public event EventHandler BindControl2;
       // Notify the object registered object (EventHandler(ctrl1_BindControl2))
        protected virtual void OnBindControl2(System.EventArgs e)
        {
            if (BindControl2 != null)
            {
                BindControl2(this, e);
            }
        }
       // Raise the event
        private public void Button1_Click(object sender, System.EventArgs e)
        {
            OnBindControl2(e);
        }
5.  Open control2.ascx.cs and add the following code inside the control2 class:
        public void BindPreview()
        {
            Response.Write("Bind Preview worked");
        }
6.  Open WebForm1.aspx and add both user controls to the page separated by breaks <br>.
6a.  Rename them from Control1 and Control2 to ctrl1 and ctrl2.
7.  Open WebForm1.aspx.cs and add the following code to the WebForm1 class:
        protected control1 ctrl1;
        protected control2 ctrl2;

        private void Page_Load(object sender, System.EventArgs e)
        {
             // Register the event handler
            ctrl1.BindControl2 += new EventHandler(ctrl1_BindControl2);
        }
       // Define the eventhandler
        private void ctrl1_BindControl2(object sender, System.EventArgs e)
        {
            ctrl2.BindPreview();
        }
Reasons I made the changes:
<strike>protected System.Web.UI.WebControls.Button Button1;</strike>
- Error 1 The type 'control1' already contains a definition for 'Button1'
<strike>private</strike> public
- Error 2 'control1.Button1_Click(object, System.EventArgs)' is inaccessible due to its protection level
6a.  Rename them from Control1 and Control2 to ctrl1 and ctrl2.
VWD Express names the Controls to Control1 and Control2 by default.
protected control1 ctrl1;
protected control2 ctrl2;
Error 4 The type 'WebForm1' already contains a definition for 'ctrl1'
Error 5 The type 'WebForm1' already contains a definition for 'ctrl2'
Please let me know if I've misunderstood something or need to have dealt with the errors in a different way.
Thanks very much.
Regards
Gary

Gary Bartlett
gb at prodsol dot co dot nz
+64 9 473-9530
+64 21 776-390
http://www.prodsol.co.nz - Dramatic improvement through pattern-level intervention
0
GaryBartlett
4/25/2006 2:25:58 AM
I have a simpler problem -- I want the click event for a button on the parent page to make the child control refresh its data.  The parent has a form that results in a row being added to a database, and the child has a view of the pertinent rows.  On submitting the form, the table needs to be refreshed...

So I went through this example, and got it working, except the compiler was flagging the equivalent statement for
public event EventHandler BindControl2;
telling me that "BindControl2" was never used.
Long story short, I ended up commenting out ALL the event handler business, and everything I needed the control to do could be in its Page_Load().  The only think left was the InitializeComponent() line:

this.btn1.Command += new System.Web.UI.WebControls.CommandEventHandler(this.btnClick);

In my real application, I'd used <input type="button">s instead of <asp:button>, so I changed those to get the .Command event for the object...  and I'm back where I started.  The control's Page_Load() refresh of the database is either not happening, or it's happening BEFORE the database row is inserted.
Any clues??

Tom von Alten
http://fortboise.org/
0
tva
6/20/2006 8:45:52 PM
> The control's Page_Load() refresh of the database is either not

> happening, or it's happening BEFORE the database row is inserted.

Indeed.  Problem was the control's Page_Load() executed and "refreshed"
the table with stale data, THEN the click eventhandler did the DB update.
Basic page life cycle issue.
Solution is to explicitly list the control in the page's variables,
    protected UserControl1 uc1;
(where uc1 is the id given to the control in the .aspx) and then
reference the control's method in the click eventhandler,
    uc1.updateHistory();
after the DB update. For efficiency, the control's Page_Load() only
calls updateHistory if !Page.IsPostBack.  Nothing special needed vis a vis
eventhandler declaration or registration.

Tom von Alten
http://fortboise.org/
0
tva
6/21/2006 9:27:31 PM
Reply: