Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Thursday, 2 January 2014

Event Bubbling from ASP.Net User Control

When working with an ASP.Net application that has child controls nested on a page, you may need to perform some action on the parent page depending on an event which occurs on one of its child controls. For example, if a button is clicked on a child control, you may want a gridview to refresh on the parent page.

As user controls are self-contained (and possibly dynamically loaded at runtime), we cannot directly reference the ID of any element that exists on a different page. One solution would be to subscribe to the child's button click event from the parent page, but this would break some of the object oriented rules of encapsulation.

A neater solution would be to publish an event in the user control. The parent page can then subscribe to this event. With ASP.Net, this functionality already exists, via the OnBubbleEvent and RaiseBubbleEvent methods. 'Event bubbling' using these methods allows a child control to propagate events up its containment hierarchy. I found these methods extremely easy to use, and it prevents the coder from having to explicity raise custom events and subscribe to these in different levels.

Lets see how it works...


 
In my child control, the 'OnClick' code behind of my button contains the following line:

RaiseBubbleEvent(sender, new CustomClickEventArgs());

RaiseBubbleEvent sends the event data up the hierarchy to the control's parent. I've also included a custom EventArgs class - more on this in a bit.


To handle (or to further propagate the bubbled event, upwards) a control must override the OnBubbleEvent method.  A control that has an event bubbled to it does one of the following three things.
  • It does nothing, in which case the event is automatically bubbled up to its parent.
  • It does some processing before continuing to bubble the event. To accomplish this, a control must override OnBubbleEvent and invoke RaiseBubbleEvent from OnBubbleEvent.
  • It stops bubbling the event and handles the event.
In the example code below, I am catchting and handling the bubble event in my parent by overriding OnBubbleEvent:
 


    /// <summary>
    /// Handles the RaiseBubbleEvent event
    /// raised by a control
    /// </summary>
    /// <param name="source"></param>
    /// <param name="e"></param>
    /// <returns>True if event is handled, false if event needs passed to parent</returns>
    protected override bool OnBubbleEvent(object source, EventArgs e)
    {
      bool handled = false;
 
      if (e is CustomClickEventArgs)
      {
        handled = true;
        RefreshParentGridView();
        }
      }
 
      return handled;
    }
 
By returning true, I am preventing the event from bubbling up any further. Alternatively, I could execute some code in the method above and then return false. This would mean the event would bubble up to the next level which overrides OnBubbleEvent, and I would have performed some logic at each level.

In the parent class, we will only have one instance of OnBubbleEvent being overriden. This poses a slight problem if we are calling RaiseBubbleEvent for multiple different events in different child controls - how do we know what logic to perform at the parent level that is specific to the event that has been raised? Easy...
   

In the above OnBubbleEvent method, I have added a clause which checks the type of EventArgs passed from the RaiseBubbleEvent call in the child. Based on the EventArgs, we can determine which logic to execute. I created a custom EventArgs class for the type of event I was raising:

    /// <summary>
    /// Custom Event Arguments class
    /// </summary>
    public class CustomClickEventArgs: EventArgs
    {
        public CustomClickEventArgs()
        {
        }
    }
 
We could even parameterize this custom event args class to expand the logic - for example - we could use the same class for one entire user control but have a parameter, passed to the constructor, which specifies which button on the user control was clicked, and then check this value in the OnBubbleEvent method to perform separate logic.






Monday, 30 December 2013

ASP.Net Textbox - Adding Decimal Validation via JQuery

Technology:
 
ASP.Net Framework 4.0
JQuery
 
Its pretty frustrating that ASP.Net does not have built in 'decimal only' validation for texboxes. I attempted to create my own using simple Javascript, but my requirement was too complex. I needed to implement the following restrictions:
 
  • allow positive AND negative numbers (therefore numbers with a single '-' at the beginning, or with a single decimal point are allowed)
  • Validation independant of cursor location - if a number has been entered and the cursor is moved to the beginning the user may enter a negative symbol
  • No flash of invalid characters on keypress (so simple Javascript 'find & replace' won't work)
  • Allow backspace, enter, left/right arrows and other non character keypress events
 
I eventually stumbled across a neat solution at http://brianjaeger.com/process.php

To implement it, I added the jquery.limitkeypress.js file to my solution. Any textbox which required this validation was assigned the class 'decimal.' In my master page's javascript file, I had the following code to apply the jQuery to any textbox with a class of 'decimal' (I was using my own regex expression which can be passes as a parameter to the JQuery library):

// ^ - start of string anchor
// (-)? - match a '-', optional
// \d* - match zero or more digits
// \. - match a '.'
// \d{0,decPlaces} - match up to specified num of dps
// )? - decimal points are optional
// $ - end of string anchor
$('.decimal').limitkeypress({ rexp: /^(-)?\d*(\.\d{0,4})?$/ });





 

Passing Parameter values from code (C#) to SSRS

Technology:

Microsoft Visual Studio 2010 with C# & ASP.NET,  Framework 4.0
Microsoft SSRS 2005
Microsoft Sharepoint 2012

At some point, you may encounter a scenario whereby you need to pass a default value from an ASP.Net application (using C#) to an SSRS report parameter hosted on Sharepoint. For example, an application may have a 'View Report' button which takes the user to an external SSRS report hosted in Sharepoint. If the user is working with a unique set of data in their application, the report should ideally be filtered for this set of data also.

In Sharepoint, a report's URL will be:

http://<SharePoint_site>/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=/<SharePoint_Document_Library>/<Report_Name>.rdl




You can specify a report parameter name and value pair by explicitly specifying the prefix "rp:" (Note that the report parameter name must match the parameter name that is specified in the SSRS report). Here is an example to add-on a parameter with name "Month" that accepts a string value:
 
http://<SharePoint_site>/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=/<SharePoint_Document_Library>/<Report_Name>.rdl&rp:Month=January

You can specify multiple report parameter name and value pairs by explicitly specifying the prefix "rp:" separated by an '&' symbol: 
http://<SharePoint_site>/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=/<SharePoint_Document_Library>/<Report_Name>.rdl&rp:Month=January&rp:Year=2014
Multiple parameter name and value pairs can be concatenated together in a separate helper method utilising the StringBuilder class. This method can then return the full parameter string which can be appended to the main report URL in order to produce the full URL.
 
When the user clicks the 'View Report' button in the application, we can use the following statement to open the parameterised report in its report library:

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "Open", String.Format("window.open('{0}');", <reportUrl>), true);