Apr 28 2006

Modal Dialog Window Caching Problem

Category: ASP.NET 1.x | ASP.NET 2.0 - GeneralBil@l @ 09:35

Hello:

Suppose you open a Modal Dialog window inside your ASP.NET page. In that dialog window, you have a GridView, DataGrid, or whatever control. Do some changes on that control, you will see that the data has changed right?

Ok, then close the dialog window, then open it again from the ASP.NET Page, you will see the old data and not the data you changed last time, right?

Ok, this is because the data has been cached by the Modal Dialog. It seems that this is how Modal Dialog Windows are built to cache.

To overcome this, you would need to add the following in the top of the ASP.NET page that is being opened with the Modal Dialog:

<%@ OutputCache Location="None" VaryByParam="None" %>

Hope that helps,

Regards

Tags: ,

Apr 25 2006

Define Custom Events in UserControls

Category: ASP.NET 1.x | ASP.NET 2.0 - GeneralBil@l @ 17:55

A very common question on the ASP.NET forums is:

How to define an event in a UserControl, and process this event in the Page holding this UserControl?

The answer is simple, follow this post, and you will be able to define your own events very easily.

We have the following UserControl file together with the Code Behind as follows:

<%@ Control Language="c#" AutoEventWireup="false" Codebehind="EventUserControl.ascx.cs" Inherits="UserControls.EventUserControl" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
<P>Choose a Country:&nbsp;&nbsp;
 <asp:DropDownList id="ddlCountry" runat="server">
  <asp:ListItem Value="Australia">Australia</asp:ListItem>
  <asp:ListItem Value="Canada">Canada</asp:ListItem>
  <asp:ListItem Value="Kuwait">Kuwait</asp:ListItem>
  <asp:ListItem Value="Lebanon">Lebanon</asp:ListItem>
  <asp:ListItem Value="Saudi Arabia">Saudi Arabia</asp:ListItem>
  <asp:ListItem Value="USA">USA</asp:ListItem>
 </asp:DropDownList></P>
<P>
 <asp:Button id="btnSubmit" runat="server" Text="Select"></asp:Button></P>

The code behind has been enriched with many comments to make your life easy while reading the code:

namespace UserControls
{
 #region Imports
 using System;
 using System.Data;
 using System.Drawing;
 using System.Web;
 using System.Web.UI.WebControls;
 using System.Web.UI.HtmlControls;
 #endregion

 #region Class Declaration
 public class EventUserControl : System.Web.UI.UserControl
 {
  #region Controls
  protected System.Web.UI.WebControls.DropDownList ddlCountry;
  protected System.Web.UI.WebControls.Button btnSubmit;
  #endregion
 
  #region Delegate Declaration
  // Step 2
  // Define the handler that will handle the event fired by the Button
  // It takes two arguments, the sender and a parameter of type ButtonEventArgs.
  // The ButtonEventArgs will hold the country that was selected
  // So the event handler in the ASPX page, should have the same signature
  // as that of the handler, of the event fired by the UserControl
  public delegate void ButtonClickedHandler (object Sender, ButtonEventArgs e);
  #endregion

  #region Event Definition
  // Step 3
  // Define an instance of the event handler,
  // this instance shall be filled with the event handler
  // that will be defined in the ASPX page
  public event ButtonClickedHandler ButtonClicked;
  #endregion

  #region OnEvent Event
  // Step 4
  // You always need the "On" method that will check if
  // the above event has been registered with an event handler or not
  // if it has been registered, then it will fire that event in the ASPX page
  // the page that is holding the UserControl
  public virtual void OnButtonClicked(ButtonEventArgs e)
  {
   if (ButtonClicked != null)
   {
    ButtonClicked(this,e);
   }
  }
  #endregion

  #region Control Events
  private void Page_Load(object sender, System.EventArgs e)
  {
   
  }
  private void btnSubmit_Click(object sender, System.EventArgs e)
  {
   string ddlSelectedValue = this.ddlCountry.SelectedItem.Text;

   // Step 5
   // Get a new instance of ButtonClickedArgs, fill it with the
   // Country that has been selected
   ButtonEventArgs objBCA = new ButtonEventArgs();
   objBCA.CountrySelected = ddlSelectedValue;

   // Call the method that will fire the event in ASPX page
   OnButtonClicked(objBCA);

  }
  #endregion

  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   InitializeComponent();
   base.OnInit(e);
  }

  private void InitializeComponent()
  {
   this.btnSubmit.Click += new System.EventHandler(this.btnSubmit_Click);
   this.Load += new System.EventHandler(this.Page_Load);
  }
  #endregion
 }
 #endregion

 #region ButtonEventArgs Definition
 // Step 1
 // An object can extend the EventArgs object
 // and adds its own fields to it
 // to be able lto gather more data
 // about the event fired
 public class ButtonEventArgs : EventArgs
 {
  #region Private Fields
  private string m_CountrySelected;
  #endregion

  #region Public Properties
  public string CountrySelected
  {
   get {return this.m_CountrySelected;}
   set {this.m_CountrySelected = value;}
  }
  #endregion

  #region Constructors
  public ButtonEventArgs()
  {}

  public ButtonEventArgs(string p_CountrySelected)
  {
   this.m_CountrySelected = p_CountrySelected;
  }
  #endregion
 }
 #endregion

}

Then, the ASPX page that will hold the UserControl is defined below, through both the Code-Behind and ASPX page:

<%@ Page language="c#" Codebehind="TestEventUserControl.aspx.cs" AutoEventWireup="false" Inherits="UserControls.TestEventUserControl" %>
<%@ Register TagPrefix="uc1" TagName="EventUserControl" Src="EventUserControl.ascx" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
 <HEAD>
 </HEAD>
 <body MS_POSITIONING="GridLayout">
  <form id="Form1" method="post" runat="server">
   <uc1:EventUserControl id="EventUserControl1" runat="server"></uc1:EventUserControl>
  </form>
 </body>
</HTML>

The code behind is as follows:

#region Imports
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
#endregion

namespace UserControls
{
 public class TestEventUserControl : System.Web.UI.Page
 {
  #region Define UserControl
  // Step 1
  // Define an instance of the UserControl
  // to be able to add an event handler
  protected EventUserControl EventUserControl1;
  #endregion

  private void Page_Load(object sender, System.EventArgs e)
  {
   
  }
  
  // Step 3
  // The event handler, whose signature is the same as the ButtonClickEventHandler
  // that will be used to handle the event fired by the UserControl
  private void EventUserControl_Fired(object Sender, ButtonEventArgs e)
  {
   Response.Write("You have choosen: " + e.CountrySelected);
  }

  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   InitializeComponent();
   base.OnInit(e);
  }
  
  private void InitializeComponent()
  {   
   this.Load += new System.EventHandler(this.Page_Load);

   // Step 2
   // Registering the ButtonClick event with the event handler on the ASPX page
   this.EventUserControl1.ButtonClicked += new UserControls.EventUserControl.ButtonClickedHandler(EventUserControl_Fired);
  }
  #endregion
 }
}

Now, you can create a new Web Application, make sure to name the Application UserControls, create a user control called EventUserControl.ascx and a page called TestEventUserControl.aspx. Those names are just named so that you can run the above code without any changes, however, feel free to change them to whatever names you want.

Hope I was able to make it easy on you, on how to define events inside UserControl and handle them in the ASPX page that is holding the UserControl.

HTH,

Regards

 

Tags: ,

Apr 24 2006

DNN - FixLogin - Revisted

Category: DotNetNukeBil@l @ 09:31

I have made slight changes on the FixLogin module in such a way, the super user or the *host* account will be able to change the *Redirect To* page online, using the DNN website.

In the first version, although I had a Setting variable to change that page, however, there was no way for anyone to change it, since the module was all the times active, and always redirecting to another page.

So now, the super user when logged in, the module will be disabled. This allows him/her to change the Redirect To page.

You can download the new version @: DotNetNuke-FixLog 2

HTH,

Regards

Tags:

Apr 23 2006

Traverse a TreeView in ASP.NET 2.0

Category: ASP.NET 2.0 - GeneralBil@l @ 13:54

I'm working those days on an application, which relies a lot on TreeView Control in ASP.NET 2.0. However, it is not just working with it out of the box, I am forced to go down and program with the control.

However, I was trying to traverse a Tree and thought of sharing with you this piece of code:

    private void TraverseTreeView(TreeNodeCollection p_NodeCollection, int p_Level)
    {
        foreach (TreeNode _TreeNode in p_NodeCollection)
        {
            for (int i = 0; i < p_Level; i++)
            {
                Response.Write("&nbsp;&nbsp;&nbsp;");
            }

            if (_TreeNode.ChildNodes.Count > 0)
            {
                Response.Write("<b>" + _TreeNode.Text + "</b>" + "<br>");
                TraverseTreeView(_TreeNode.ChildNodes, p_Level + 1);
            }
            else
            {
                Response.Write(_TreeNode.Text + "<br>");
            }
        }
    }

You would call this method as:

TraverseTreeView(this.TreeView1.Nodes, 0);

 

Hope this helps you working with your TreeView.

Regards

Tags:

Apr 22 2006

The Observer Pattern

Category: Design PatternsBil@l @ 10:25

The pattern I am going to talk about today is the Observer Pattern. Another new and cool pattern to discuss.

Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Not clear? Its ok, we'll restate again.

The idea is simple, take the example of the publisher and subscibers!

A newspaper paper publisher publihes newspaper every morning right? nothing new :)

Suppose I am company X, and want to have the newspaper arrive to my officies every morning.

So I(observer) go to the publisher (subject) and tell him/her please I want to subscribe to your newspaper to get my newspaper (update) every morning.

What happens is that, once a new newspaper is published every morning, the publisher will update my office with that new newspaper.

So the main players are the Subject and Observer. The observer registers with the Subject, then the subject's responsiblity to update the state of each observer registered. Observers can register and unregister from a subject.

Usually we use two interfaces, one for the subject and one for the observers. This way any object wants to register with the subject has only to implement that interface.

Hope this helps you,

Regards

Tags:

Apr 22 2006

Visual Studio 2005 Express Free For Ever

Category: ASP.NET 2.0 - GeneralBil@l @ 10:05

I read a great post from some time, that Microsoft has decided to make the Visual Studio 2005 Express Editions free for ever!!

Read more here:

Visual Studio Express Editions are Free Forever

Regards

 

Tags:

Apr 21 2006

The Strategy Pattern

Category: Design PatternsBil@l @ 19:09

This is the first post for me in the field of Design Patterns. I am new to this field, but decided to summarize each pattern I cover in my great book called: Head First Design Patterns.

The Strategy Pattern:

Defines a family of algorithms, encapsulates each one, and makes them interchangable. Strategy let the algorithm vary independently from clients that use it.

The idea is as follows: Suppose you are developing a game where you will have different players or characters. Each character can make use of one Weapon at a time, but can change the weapon at any time during the game.

We have several characters in the game, we think directly of having a base Character object, and each character can inherit from that base class.

Now, as mentioned, each character needs to use a weapon, which is nothing but a behaviour, but also wants to be able to change that weapon at run time. We might have different kinds of Weapons. Every weapon has a behaviour, so you might think of having an Interface called Weapon and all the behaviours of that Weapon will be represented by algorithms or objects implementing that interface, each having its own implementation of the Weapon, hence each having its own algorithm.

So the base class we had before, now has its own behaviour implemented by the family of algorithms that implement the Weapon Interface.

This way, any object inheriting from the base Character class, can use any Weapon implementation, and can change from one Weapon to another at run time, but means of an inherited member placed in the base Character class of type Weapon Interface.

So when you have several objects that are basically the same but only differ in their behaviours. It is better to use the Strategy pattern, in which you seperate the objects from their behaviour, making the addition of new behaviours easy, and then alalowing those objects to change any behaviour at run time and hence getting rid of the subclassing method to provide common behaviour to the objects.

Hope this helps,

Regards

Tags:

Apr 18 2006

ASP.NET 2.0 Training Center

Category: ASP.NET 2.0 - GeneralBil@l @ 13:25

I wanted to share with you a great website I passed by today:

ASP.NET 2.0 Training Center

Has lots of great resources through articles, webcasts, and others.

Make sure to visit that site.

Regards

Tags:

Apr 18 2006

Paging With ObjectDataSource in One Trip

Category: ASP.NET 2.0 - GeneralBil@l @ 11:55

This post assumes you have the previous post on the DataObjectTypeName and ObjectDataSource .

Usually, when we want to allow paging when we are using ObjectDataSource, we should enable paging in both the Data-Bound Control (GridView an example) and the ObjectDataSource.

  • GridView: AllowPaging and off course you need to set PageSize.
  • ObjectDataSource: EnablePaging, also you need to set the:
    • MaximumRowsParameterName="maxRows"
    • StartRowIndexParameterName="startRowIndex"
    • SelectCountMethod="RecordCount"

The method specified in the SelectMethod should now have 2 parameters:

  • int maxRows
  • int startRowIndex

The key point I wanted to show here is the following:

When you want to allow paging, you should add a method called SelectCountMethod, this method is used by the ObjectDataSource to know how many pages there will be.

An old conception for me has been that, we are doing two database round-trips. One to get the data and one to get the Record Count.

This is not true anymore!!! Why?

Let me explain, if the methods in the data mapper class are instance methods that is, not defined with static methods, then ODS will create an instance of the object specified in the TypeName, and access those methods, then disposes that instance.

However, if we had enabled paging, and both the SelectMethod and SelectCountMethod are both instance methods, then, the same instance will be used to access those two methods. So now, inside your Select method, you can get the count of the total records, and store it in a private instance, and then have a SelectCountMethod return that instance. This way, in one shot, you got both values, and since the "same instance" is created by the ODS, means you can for sure make use of the value of the record count, check this sample:

   [DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
    public List<Employee> Get()
    {
        // your logic to retrieve all records

        // Get the Count record
        _CountRecords = (int)dr["Count"];

        return new List<Employee>();
    }

    public int RecordCount()
    {
        return _CountRecords;
    }

Hope this helps you,

Regards

Tags:

Apr 18 2006

DataObjectTypeName and ObjectDataSource

Category: ASP.NET 2.0 - GeneralBil@l @ 10:32

For most of you using the ObjectDataSource, you must have passed by DataObjectTypeName property of the ObjectDataSource.
I have been working with it for a while, but thought of sharing with you the beauty of that property.

Usually, ObjectDataSource uses two modes to pass parameters for the data mapper's methods:

  • Simple Data Types (string, int, etc ...)
  • Custom Objects (Input for methods would be an object)

When you set the DataOjectTypeName ="MyClass" of the ObjectDataSource, then the following should be valid:

  • All CRUD (Create, Retrieve, Update, Delete) methods specified in the TypeName property of ObjectDataSource should expect a parameter of type "MyClass" as an input parameter, except for the Retrieve method for sure. For instance:
    public static void Delete(MyClass p_Myclass)
    { }
  • The MyClass is a simple object, that has some public properties like: ID, Name, Email, etc ... Make sure that the properties' names match exactly witht the names of the fields displayed by the Data-Bound Controls. For instance, if you have a property called ID in the MyClass, the GridView displaying the records, should have the name of the BoundField representing the ID as "ID", you see how names match?
  • No more needed to list all Select,Update,Insert,Delete parameters in the ObjectDataSource. At runtime, an instance of type MyClass is created for us out of the Data-Bound Control (example: GridView) and sent to the data mapper's methods!

I asked myself, wouldn't that be waste of time if I am sending the whole object to the Delete Method, in a time, I only need for example ID to delete a record? Well, the answer came back directly from the ObjectDataSource as follows: The proccess is so inteligent that when the Delete Button is clicked, the key specified in the DataKeyNames property of the GridView for example, is supplied to the MyClass instance, so only the ID is filled and the rest of fields are igonored. Isn't that great?

Check this simple example to see How Stuff Works ;)

GridView + ObjectDataSource       

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                <asp:BoundField ReadOnly="true" DataField="EmployeeId" HeaderText="EmployeeId" SortExpression="EmployeeId" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
            </Columns>
        </asp:GridView>
        &nbsp;</div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="Employee"
            DeleteMethod="Delete" SelectMethod="Get" TypeName="EmployeeDal"></asp:ObjectDataSource>

Employee and EmployeeDal

public class Employee
{
    #region Private Members
    private int m_EmployeeId;
    private string m_FirstName;
    private string m_LastName;
    #endregion

    #region Constructors
    public Employee()
    { }

    public Employee(int p_EmployeeId, string p_FirstName, string p_LastName)
    {
        this.m_EmployeeId = p_EmployeeId;
        this.m_FirstName = p_FirstName;
        this.m_LastName = p_LastName;
    }
    #endregion

    #region Public Properties
    public int EmployeeId
    {
        get { return this.m_EmployeeId; }
        set { this.m_EmployeeId = value; }
    }

    public string FirstName
    {
        get { return this.m_FirstName; }
        set { this.m_FirstName = value; }
    }
    public string LastName
    {
        get { return this.m_LastName; }
        set { this.m_LastName = value; }
    }
    #endregion
}

--------------------

using System;
using System.Data;
using System.ComponentModel;
using System.Configuration;
using System.Collections.Generic;

[DataObjectAttribute]
public class EmployeeDal
{
    public EmployeeDal()
    {   }

    [DataObjectMethodAttribute(DataObjectMethodType.Delete, true)]
    public static void Delete(Employee p_Employee)
    {
        // your logic to delete a record using the parameter EmployeeId as follows
        int EmployeeId = p_Employee.EmployeeId;
    }
   
    [DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
    public List<Employee> Get()
    {
        // your logic to retrieve all records

        return new List<Employee>();
    }
}

Hope this helps,

Regards

Tags: