Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 426
  • Last Modified:

Using abstract class to call a method of a page

I have a page

Deals.aspx

in this page I have a usercontrol that is a grid. When items in this grid are updated I need to update the charts on the page (Deals.aspx).

The Deals.aspx page has subroutines that reload the charts

loadProducts() 'the chart

how do I, from the usercontrol, call Deals.loadProducts() ? I've made it a Public sub. I tried...

dim obj as new Deals
obj.loadProducts() ' but the chart is not recognized in the new Deals.aspx

It looks like it can be done with and abstract class and inheritance but I'm lost on how to put it together.

Thanks!
0
md0333
Asked:
md0333
  • 8
  • 6
  • 2
  • +1
2 Solutions
 
Rikin ShahMicrosoft Dynamics CRM ConsultantCommented:
Create a custom event on your user control using delegates and when update event is fired you can call function for updating charts.

http://www.devasp.net/net/articles/display/711.html
0
 
md0333Author Commented:
OK... still must be doing something wrong.

Put this in the Deals.aspx page

    Public Delegate Sub updateMyCharts()

    Public Sub updateAllCharts()
        loadProducts()
    End Sub


And trying to put this in my usercontrol it does not recognize UpdateMyCharts() without putting Deals. in front of it. then it doesn't see UpdateAllCharts() at all

        Dim obj As DealLog.updateMyCharts  'not seen without page in front
        obj = AddressOf updateallcharts()     'does not recognize sub
0
 
md0333Author Commented:
Any ideas what is wrong? Why the code I  tried is not working...

suggestions??
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
md0333Author Commented:
I changed the code in the usercontrol to;

        Dim obj As New DealLog.updateMyCharts(AddressOf DealLog.updateAllCharts)
        obj.updateAllCharts()

The first line tells me "Reference to a non-shared member requires and object reference"
Line 2 says "updateAllCharts is not a member of DealLog.updateMyCharts"
0
 
md0333Author Commented:
Here's the answer

I created a public sub in the .aspx page

Public Sub ucUpdateCharts()
    .... code here
End Sub

In my usercontrol I put this code where I need to call the page sub

Me.Page.GetType.InvokeMember("ucUpdateCharts", System.Reflection.BindingFlags.InvokeMethod, Nothing, Me.Page, New Object() {})
0
 
ThogekCommented:
That GetType.InvokeMember approach should work, but the reflection API that it's using isn't very efficient compared to calling the method directly...

Have you tried something simpler like:

CType(Me.Page, Deals).ucUpdateCharts()

Open in new window

0
 
md0333Author Commented:
Worked also... and more efficient is better.

Thank you!
0
 
md0333Author Commented:
I would like to award the points to Thoqek...

Thank you.
0
 
daveamourCommented:
Your solution is horribly wrong!

Your user control is calling a method in the page.  Think of a simpler scenario where you have a button in a page.  You listen to the event click from your page and then run code in response.

The button should not need to know about the object containing it.

Delegates and events are the correct solution as suggested by other users.

http://www.audacs.co.uk/ViewPage.aspx?PageID=474
http://www.audacs.co.uk/ViewPage.aspx?PageID=476
0
 
md0333Author Commented:
I tried using delegates but I can't seem to get the syntax correct...

on my main page I have
    Public Delegate Sub myDel()

    Public Sub ucUpdateCharts()
        loadChart()
    End Sub

And in usercontrol I have tried a few different ways but none work

        Dim del As DealLog.myDel

        del = New DealLog.myDel(AddressOf ucUpdateCharts) 'ucUpdateCharts is not Declared

        del = AddressOf ucUpdateCharts 'ucUpdateCharts is not Declared


0
 
daveamourCommented:
Ok this is a closed question so carry on with wht you have but I will code a solution for you, not fro points, just in the interests of good code.

Very busy at the moment though so I will do this at the weekend and then come and post it here.
0
 
md0333Author Commented:
I have no problem giving out another set of points... And I appreciate the help.
0
 
ThogekCommented:
daveamour has a good point.  What I posted, and what you have, will work, but it creates an awareness by the control of its containing page that arguably violates some basic OO concepts, and would make re-using that control in another page more troublesome than it should be.

OTOH, simply having the control publish a public custom GridUpdated event to which the page can choose to subscribe and respond as it will, would decouple the dependency much more cleanly...
0
 
daveamourCommented:
Yep Thoqek is spot on

This is what we should be striving for - clean, decoupled, cohesive code which is easy to maintain, reuse and extend!

0
 
daveamourCommented:
Ok this is all done.  I did it in C# and VB.net.

So we have a control and a page containing the control.  The control contains a button and when it is clicked the containing page will run code as it has subscribed to the event which I have added to the control.  Have a look and see if it makes sense.

The aspx is the same for C# and VB.net with just the code behind being different.


<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="VBServerControls._Default" %>

<%@ Register src="SomeControl.ascx" tagname="SomeControl" tagprefix="uc" %>

<!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></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <uc:SomeControl ID="SomeControlInstance" runat="server" />

        <p>
            <asp:Literal ID="Message" runat="server" EnableViewState="false"></asp:Literal>
        </p>    
    </div>
    </form>
</body>
</html>

Open in new window

0
 
daveamourCommented:
Sorry I submitted that by mistake!

Here is the rest - you will have to change @ Page Language="vb" as required though!

I can send you the solution too if you like.
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="SomeControl.ascx.vb" Inherits="VBServerControls.SomeControl" %>
<div style="border: 1px solid #000; padding: 20px; width: 400px; height: 80px; font-family: Verdana;">
    <p>
        This is my server control with a button <asp:Button ID="MyButton" 
            runat="server" Text="Click Me" onclick="MyButton_Click" />
    </p>
</div>

Public Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub

    Protected Sub SomeControlInstance_ButtonClicked() Handles SomeControlInstance.ButtonClicked
        Message.Text = "The button was clicked (VB)"
    End Sub

End Class

Public Class SomeControl : Inherits System.Web.UI.UserControl
    Public Event ButtonClicked(ByVal sender As Object, ByVal e As EventArgs)

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub

    Protected Sub MyButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles MyButton.Click
        RaiseEvent ButtonClicked(sender, e)
    End Sub
End Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CSharpServerControls
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            SomeControlInstance.ButtonClicked += new EventHandler(SomeControlInstance_ButtonClicked);
        }

        protected void SomeControlInstance_ButtonClicked(object sender, EventArgs e)
        {
            Message.Text = "The button was clicked (C#)";
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CSharpServerControls
{
    public partial class SomeControl : System.Web.UI.UserControl
    {
        public event EventHandler ButtonClicked;
        
        protected void Page_Load(object sender, EventArgs e)
        {
           
        }

        protected void MyButton_Click(object sender, EventArgs e)
        {
            if (ButtonClicked != null)
            {
                ButtonClicked.Invoke(sender, e);
            }
        }
    }
}

Open in new window

0
 
daveamourCommented:
Thanks for the points :)
0

Featured Post

Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

  • 8
  • 6
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now