Link to home
Start Free TrialLog in
Avatar of smooga
smooga

asked on

Using user input to affect page layout on postback

Ok, that was not the most descriptive title, but my question is kind of specific and I couldn't sum it all up in one line.  Here's my problem...

I have a page which contains a number of dynamically generated datagrids.  Each datagrid contains rows of data for a group of people... each row representing a person in that group.  The number of groups, and hence the number of datagrids, depends on data stored in a database.  So, on Page_Load, I go to the database, determine the number of groups, create the datagrids, populate them, and then add them to a placeholder object which is declared in my aspx page.  This works fine.  I'm running into trouble when I try to alter this data based on user input.  One of the columns in the datagrid is a DropDownList which contains the group numbers of the groups on the page.  So, if I have 3 group datagrids on the page, the DropDowns contain the numbers 1, 2, and 3.  Each of these defaults to its group number... so, the "group 1" dropdowns have '1' selected, the "group 2" dropdowns have '2' selected, etc.  Now, I want to have a user be able to move people to different groups by changing their dropdown value to a different group number and the clicking a submit button.  When the page is submitted, I want to update the database for the people with altered dropdowns and then reload the page off the new database data.  This, however, seems to be easier said than done.  When I click submit, the original data is first loaded and THEN the button click method is called.  In the button click method I am determining which dropdowns were changed and updating the database accordingly, but this doesn’t really help since the page has already rendered the old data.  Furthermore, even if I could get the buttonclick method to execute first, it wouldn’t work because I need to access the datagrids to get at the dropdowns… and the datagrids aren’t created until after Page_Load is called.  So I guess my questions are these:

Can I collect the changed dropdown data on the client-side, pass it to the server on submit, alter the database BEFORE Page_Load, and then render the page?

Or, is there some other preferred way of handling this type of situation?

Please help shed some light on this for me!
Avatar of Edward Diaz
Edward Diaz
Flag of United States of America image

Yeah, it definitely sounds like a postback problem.

What does your Page_Load() look like??

 Do you have something similar to the code:

Sub Page_Load(sender as Object, e as EventArgs)

If Not Page.IsPostBack

myfunction()
End If

End Sub

I'm thinking you have your Sub call that contains the binding of your grids is not in the If Not Page.IsPostBack section. Although, I could be wrong obviously as I'm taking a complete stab in the dark.

Kittrick
Avatar of smooga
smooga

ASKER

Well, I had put in the !IsPostBack condition (using C#), but since I'm creating all of the grids dynamically in the Page_Load method and then adding them to a placeholder, if I surround that code with "if (!IsPostBack ) {...}", the page just comes back blank after the submit.  None of the grids are created and I cannot access the dropdowns (which are also not created) to determine what the user changed.
hmmm...I still think it's definitely a postback problem, did you try the code if it is postback??

could you post your code?? I can read both vb.net and C#.

Kittrick
Avatar of smooga

ASKER

"did you try the code if it is postback"
I'm not sure what you mean.  Like I said, when I have the !IsPostBack condition, the datagrids are not created on postback.  Am I msunderstanding what you're asking?  

Unfortunately, I cannot post my code at the moment.  I'm no loger in the office, and the code that I zipped and emailed home was somehow corrupted.  I can post some simple pseudocode for now though...

Page_Load ()
{
    CreateGrids();
}

CreateGrids()
{
    // Connect to the database and get the data
    // Create the datagrids and bind to the data
    // Add the datagrids to the PlaceHolder object in the .aspx page
}

OnDataBind()
{
    // Create dropdownlists and add them to the datagrid
}

OnButtonClick()
{
    // Access the dropdownlists in the datagrids and determine if the selectedindex has changed
    // If so, update the database
}


The OnDataBind method is called for each datagrid and this is how I'm adding my dropdownlists.  This works correctly.  
When I surround the call to CreateGrids() with the !IsPostBack condition, the grids are only created on the initial page load.  When the page loads from a submit button click, CreateGrids is never called and they are never created.  This is the behavior I would expect.  Am I missing something here?  Should my code be laid out differently?
My suggestion:
Move calling CreateGrids() to Page_Prerender event handler
And in OnButtonClick you can access your datagrids from PlaceHolder1.Controls.
Iterate through them and compare their values to those in the database,
if something changed, modify the database.

After OnButtonClick executes, Page_Prerender will execute
CreateGrids and recreate those datagrids.

Avatar of smooga

ASKER

So let me make sure I understad how ASP.NET works in this scenario...

When the page initially loads, the grids will be created for the first time.  When a user clicks the button to submit, a request is made back to the server.  Page_Load is called and then OnButtonClick is called.  When OnButtonClick is called, it has access to the controls that were originally placed in the PlaceHolder control?  How is it possible that those controls still exist on the return to the server?  Are they persisted through the viewstate?

I'm headed to the office now.  Will try this out first thing.  Thanks
yes, even dynamically created controls will be kept in viewstate.

You can try it out by creating a simple control and add it to the page,
then you can do a postback(such as click a button), you will see the control
will still be there.
Avatar of smooga

ASKER

Ok, I've changed the code as you suggested, but it's still not working.  The initial page load works fine, but when I click submit, the request is made to the server, OnButtonClick is called, it looks in the PlaceHolder control for the datagrids, but the PlaceHolder is empty.  It doesn't seem to be retaining the PlaceHolder/Datagrid data in the viewstate... even though I explicitly set EnableViewState=true for the PlaceHolder and DataGrids.  This is how my code is laid out now:

Page_Prerender()
{
    CreateGrids();
}

CreateGrids()
{
    // Connect to the database and get the data
    // Create the datagrids and bind to the data
    // Add the datagrids to the PlaceHolder object in the .aspx page
}

OnDataBind()
{
    // Create dropdownlists and add them to the datagrid
}

OnButtonClick()
{
    // Access the dropdownlists in the datagrids via the PlaceHolder control and determine if the selectedindex has changed
    // If so, update the database
}
My fault, I made a mistake while testing.

I think dynamically generated controls are not preserved in postback.
Avatar of smooga

ASKER

I must not understand viewstate and postback fully then... here's a test page:

private void Page_Load(object sender, System.EventArgs e)
{
     this.EnableViewState = true;
     
     if ( !IsPostBack ) {
      myLabel = new Label();
      myLabel .Text = "Testing postback!";
      myPlaceholder.Controls.Add( myLabel );
     }
}

On postback the label will not be created... but my understanding of what laotzi2000 said above is that the label should still be loaded and displayed from the viewstate.
Avatar of smooga

ASKER

Ahhh... I didn't see your last post before I posted mine.

Ok, so if dynamically created controls are not preserved in postback, how do we handle this situation??
I think you can write some client side script to record what changes have
been made and store it in a hidden field on the page.
On postback, read from this hidden field and compare it with the database.
smooga,

you have to understand about dynamic controls.

1. They have to be created and added to the page tree when the Page's Init method fires

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
      //
      // CODEGEN: This call is required by the ASP.NET Web Form Designer.
      //
      InitializeComponent();
      base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{    
      this.Load += new System.EventHandler(this.Page_Load);
      this.Init += new System.EventHandler(this.Page_Init);

}
#endregion

private void Page_Init(object sender,EventArgs e)
{
      /// add your controls to the page hierarchy
      /// view state cannot be accessed now
}

private void Page_Load(object sender,EventArgs e)
{
      /// you can access viewstate
}
Avatar of smooga

ASKER

So I'm thinking along the lines of my original question again... collect the changed dropdown values on the client-side using javascript, stash them in a hidden field, post to the server, pick up that data in OnButtonClick and update the database.  Maybe not the most elegant/pure-.NET way, but it should work.  Stay tuned
Avatar of smooga

ASKER

I keep posting before reading the other posts...

laotzi2000, exactly what I was thinking :)

b1xml2, can you clarify something for me?  What does moving that code to Page_Init achieve?  Does it allow their viewstate to persist on postback?
2. the dynamic controls you add must be given fixed IDs upfront, so that there is no mixup during postbacks.

3. Now comes the million dollar question: If we depend on user interaction and viewstate in the first place to determine what controls to add, well you're stuffed.

SITUATION A
=========
1. Need to create controls immediately when the Init event fires.
2. Cannot access ViewState for user input

SITUATION B
=========
1. User input done
2. View State holds partial or all of information

SOLUTION
======
1. Move storage of information which determines the whys and hows of the dynamic control away from ViewState..
2. Alternative storage would be Session (Across pages so if the user presses control+N and the settings for MSIE is to reuse existing windows, you end up having 2 windows sharing the same session..yikes!!)
OR
3. Move storage of information to database or temp xml and set the keys inside hidden input. Request.Form collection is accessible and quite apart from ViewState.
OR
4. Store keys and write out classes that handle the control generation according to the keys..

smooga... by adding controls inside Page_Init, it is as though they were written manually, so the viewstate will be persisted BEFORE the button's onclick event fires up...

It is a well known method, since the view state does not begin to be reconstituted until after the Init Event. If you write it in the Load Event, it will take some time to catch up whilst other events have already fired off
it's easy to store the controls created dynamically.
What's difficult is to construct a control from the web page with user
change.
b1xml2 is correct, though he is very clear on some point.

Dynamically created control's viewstate can be preserved if it is created in Page_Init

You can try this one:
   Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
         Dim c As New TextBox
        PlaceHolder1.Controls.Add(c)
    End Sub

On postback, the user input in Textbox is preserved and is available on server side.
I'm still playing around with it and I found b1xml2 not correct.
But I think I have found a solution with it.
I found out that if you create your controls dynamically in or before Page_Load event handler,
your controls will be automatically populated from data in viewstate right after Page_Load.

So if you create your dropdownlists in or before Page_Load, it will contain user input.

My suggestion:
Create Datagrid in Page_Load
Create empty Dropdownlists for DataGrids in Page_Load too
In OnDataItemBound, set proper values for dropdownlist if it is not postback

Then, in your button_click function, you can get the user selection from the dropdownlists
Avatar of smooga

ASKER

laotzi, I'm going to try the client-side scripting solution in the meantime.  Look forward to hearing other solutions though.

b1xml2, thanks for all the info... your solutions might be a little involved for my needs, but they're definitely informative.  Thanks.

Once I finally get this problem licked, I'll split the points between both of you since you both had valuable input.  Sound good?
Avatar of smooga

ASKER

laotzi2000, trying... I think the key might be to put the !IsPostBack only in OnDataItemBound.  Good call.  brb...
Avatar of smooga

ASKER

Ok, no, I don't think that's possible.  How can I create the dropdownlists before OnItemDataBound?  They are currently being created/inserted dynamically as each row of the datagrid is created.  I suppose I could create a custom DropDownList TemplateColumn class, but that seems like a bit too much work for this problem :)  Plus, I am creating a number of other objects for other columns in the OnItemDataBound method... don't see how to avoid creating them here.
When do you call the datagrid.databind in your code? In Page_Load?
And is onItemDataBound execute before Page_Load ends?(debug it to find out)
If that's case, it should be OK to put those code in OnItemDataBound.

Another note: I think you should assign a unique id manually for each dropdownlist control
(the primary key of the record must be a perfect choice)
so after Page_Load, it can find proper viewstate data for the dropdownlist control. I think
maybe this is really what the problem is.
consider this:
<%@ Page language="c#" Codebehind="DynamicControls.aspx.cs" AutoEventWireup="false" Inherits="b1xml2.ExpertsExchange.CSharp.April.DynamicControls" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
<html>
<head>
<title>DynamicControls</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">
<script language="javascript">
function persistValue(value)
{
      var el = document.forms[0]["Stage"];
      if (el) el.value = "" + value;
      alert(el.value);
}

</script>
</head>
<body MS_POSITIONING="FlowLayout">
<form id="Form1" method="post" runat="server">
<asp:PlaceHolder ID="holder" Runat="server"></asp:PlaceHolder>
</form>
</body>
</html>
and then this:
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;

namespace b1xml2.ExpertsExchange.CSharp.April
{
      /// <summary>
      /// Summary description for DynamicControls.
      /// </summary>
      public class DynamicControls : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.PlaceHolder holder;
            protected DropDownList country;
            protected DropDownList state;
            protected LinkButton submit;

            private StageList stage = StageList.None;
      
            private void Page_Init(object sender, EventArgs e)
            {
                  if (CompareEnum(Stage,StageList.Country))
                  {
                        AddCountry();      
                        
                  }
                  
                  if (CompareEnum(Stage,StageList.State))
                  {
                        AddState();
                        
                  }

                  if (CompareEnum(Stage,StageList.Submit))
                  {
                        AddSubmit();
                        
                  }

                  
            }

            private void AddCountry()
            {
                  country = new DropDownList();
                  country.ID = "country";
                  country.Attributes["onchange"] = string.Format("persistValue(this.selectedIndex == 0 ? {0} : {1});",
                        (int)StageList.FirstStage,
                        (int)StageList.SecondStage);
                  country.DataTextField = "Value";
                  country.DataValueField = "Key";
                  holder.Controls.Add(ParseControl("<div><b>Country</b>"));
                  holder.Controls.Add(country);
                  holder.Controls.Add(ParseControl("</div>"));
                  country.SelectedIndexChanged += new EventHandler(country_SelectedIndexChanged);
                  country.AutoPostBack = true;

            }

            private void AddState()
            {
                  state = new DropDownList();
                  state.ID = "state";
                  state.Attributes["onchange"] =  string.Format("persistValue(this.selectedIndex == 0 ? {0} : {1});",
                        (int)StageList.SecondStage,
                        (int)StageList.ThirdStage);
                  state.DataTextField = "Value";
                  state.DataValueField = "Key";
                  holder.Controls.Add(ParseControl("<div><b>State</b>"));
                  holder.Controls.Add(state);
                  holder.Controls.Add(ParseControl("</div>"));
                  state.SelectedIndexChanged += new EventHandler(state_SelectedIndexChanged);
                  state.AutoPostBack = true;
                              
            }

            private void AddSubmit()
            {
                  submit = new LinkButton();
                  submit.ID = "submit";
                  submit.Text = "Submit Selection";
                  holder.Controls.Add(submit);
                  submit.Click += new EventHandler(submit_Click);
            }

            private bool CompareEnum(StageList composite,StageList value)
            {
                  return ((composite & value) == value);
            }


            private StageList Stage
            {
                  get
                  {
                        if (stage == StageList.None)
                        {
                              int value = Request.Form["Stage"] == null ? 1 : int.Parse(Request.Form["Stage"]);
                              stage = (StageList)value;
                        }
                        return  stage;                  
                  }
                  set
                  {
                        stage = value;
                  }
            }

            private void Page_Load(object sender, System.EventArgs e)
            {
                  if (! Page.IsPostBack)
                  {
                        PopulateCountries();
                        
                  }
                  SetStage();
                  
                  
            }

            private void PopulateCountries()
            {
                  SortedList list = new SortedList();
                  list["US"] = "United States";
                  list["UK"] = "United Kingdom";
                  
                  this.country.DataSource = list;
                  this.country.DataBind();
                  this.country.Items.Insert(0,"Please Select Country");
            }

            private void SetStage()
            {
                  Page.RegisterHiddenField("Stage",((int)Stage).ToString());
            }

            

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.Load += new System.EventHandler(this.Page_Load);
                  this.Init += new EventHandler(Page_Init);
                  

            }
            #endregion

            

            private void country_SelectedIndexChanged(object sender, EventArgs e)
            {
                  if (this.country.SelectedIndex > 0)
                  {
                        if (this.state == null)
                        {
                              AddState();
                              this.Stage = StageList.SecondStage;
                        }
                        SortedList sl = new SortedList();
                        switch (this.country.SelectedValue)
                        {
                              case "UK":
                                    sl["WL"] = "Wales";
                                    sl["EN"] = "England";
                                    sl["SC"] = "Scotland";
                              break;
                              case "US":
                                    sl["NY"] = "New York";
                                    sl["TX"] = "Texas";
                              break;
                        }

                        state.DataSource = sl;
                        state.DataBind();
                        state.Items.Insert(0,"Please Select State");
                  }
                  else
                  {
                        this.Stage = StageList.FirstStage;
                  }
                  SetStage();
            }

            private void state_SelectedIndexChanged(object sender, EventArgs e)
            {
                  if (this.state.SelectedIndex > 0)
                  {
                        if (this.submit == null)
                        {
                              AddSubmit();
                              this.Stage = StageList.ThirdStage;
                        }
                  }
                  else
                  {
                        this.Stage = StageList.SecondStage;
                  }
                  SetStage();
            }

            private void submit_Click(object sender, EventArgs e)
            {
                  Response.Write(string.Format("<div>Country Is {0}</div>\n<div>State Is {1}</div>",country.SelectedValue,state.SelectedValue));
            }

      }

      [Flags]
      public enum StageList : int
      {
            None = 0,
            Country = 1,
            State = 2,
            Submit = 4,
            FirstStage = Country,
            SecondStage = Country | State,
            ThirdStage = Country | State | Submit
      }
}
you will see the dynamic creation of web controls and the application of the viewstate to it before the appropriate web control events are fired off. that;s how you deal with dynamic web controls
comment out the alert if you dont want to see what value is being set...
but only by understanding the viewstate and the nature of the postbacks and adding controls the way shown in the snippet, can you successfully use dynamic controls

HTH
Avatar of smooga

ASKER

Well, as far as the ID is concerned, I think that might be a problem.  Even though I specify an ID for the dropdowns (using the primary key as suggested), since they are in a datagrid, .NET is prepending "_ctl0__ctl0", "_ctl0__ctl1", "_ctl0__ctl2", etc.  I don't know if this is causing a problem, but the code still doesn't work.  

Initial load works fine.  On submit, the grids are created but the code in OnItemDataBound does not execute because of the !IsPostBack condition.  Then the OnButtonClick executes.  It looks inside the grids and throws an exception:

foreach ( DataGridItem row in dg.Items ) { // each row of the DataGrid
    DropDownList ddl = (DropDownList) row.FindControl( "groupDDL" ).Controls[ 0 ];  <-- fails here because it can't find the dropdown

    ......
}

Although I'm really curious about getting this to work the "right" way, I think I'm going to have to go with the client-side scripting method.  Spending way too much time on this and I have deadlines to worry about.
Avatar of smooga

ASKER

Thanks b1xml2.  Once again my curiostiy gets the better of me... will try this code out despite having just said I'm spending too much time on this problem :)
On more try:

remember that whether it is postback or not, you should create those dropdownlists,
so you should not put the code inside !Ispostback.
I'm pretty positive that it will work.

Cheers up.
the ids here will not relate to the child controls...so you don;t have to worry about that...you just have to ensure that your datagrid has an id,
show us a snippet (small pls) and we'll get a working code for you.

Avatar of smooga

ASKER

Well, I got it working by placing the CreateGrids code in Page_Init and giving a unique ID to the grids, but it only works if I don't use the !IsPostBack condition.  This means that on postback, the grids are being created from the database data, then onButtonClick updates the database, then the grids are recreated from the database data.  Three database hits.  Not really what I'm looking for.

I can't really post a small snippet of my code... it's pretty long.  Let me try to edit it down to just the very basics.  hold on...
I think even if you recreate the datagrids from the database in Page_Init,
it will still get viewstate data after Page_Load
Your data from the database will be lost

I have an example here:
in Page_Load
      Dim c As New TextBox
        c.Text = "haha"
        PlaceHolder1.Controls.Add(c)

you'll see that even though you set the text of the textbox to haha everytime in Page_Load,
only the user input will preserve.
So you can create the grids in Page_Init or Page_Load
It will get Populated from viewstate data after Page_Load
Then you modify the database according to these data in OnButtonClick
Then you can recreate those grids according to the database in Page_Prerender.

Quite complex.
Avatar of smooga

ASKER

Ok, here's a very edited version... not putting any !IsPostBack condition in.

private void Page_Init(object sender, EventArgs e)
{
    LoadGrids();
}

private LoadGrids() { ... } // this method calls CreateGrids for each group in the database

private void CreateGrids( DataView groupView )
{
        DataGrid groupGrid = new DataGrid();
      int groupNum = (int) groupView[ 0 ][ "Group_Number" ];
      groupGrid.ID = "groupGrid_" + groupNum;
                        
      // Set grid properties.......
      groupGrid.AutoGenerateColumns  = false;
      groupGrid.EnableViewState = true;
      groupGrid.DataSource = groupView;
      groupGrid.ItemDataBound += new DataGridItemEventHandler( OnItemDataBound );

        BoundColumn name = new BoundColumn();
      name.DataTextField = "Full_Name";

        TemplateColumn assignedGroup = new TemplateColumn();
       
      groupGrid.Columns.Add( name );
        groupGrid.Columns.Add( assignedGroup );

      groupGrid.DataBind();
      placeholder.Controls.Add( groupGrid );
}

private void OnItemDataBound( Object sender, DataGridItemEventArgs e )
{
      DataView groupView = (DataView) ((DataGrid) sender).DataSource;

      if ( e.Item.ItemType != ListItemType.Header && e.Item.ItemType != ListItemType.Footer ) {
            DropDownList ddl = new DropDownList();
            
            /*
            code to populate dropdownlist from other database data.
            */

            e.Item.Cells[ 1 ].ID = "groupDDL";
            e.Item.Cells[ 1 ].Controls.Add( ddl );
      }
}

private void UpdateButton_Click( object sender, System.Web.UI.ImageClickEventArgs e )
{
      string sqlStr = "";
                  
      foreach ( object aControl in placeholder.Controls ) {
            if ( aControl.GetType() == typeof( DataGrid )) {      // each DataGrid
                  DataGrid dg = (DataGrid) aControl;
                  foreach ( DataGridItem row in dg.Items ) {      // each row of current DataGrid
                        DropDownList ddl = (DropDownList) row.FindControl( "groupDDL" ).Controls[ 0 ];
                        // if selected index was changed, create sqlstr string
                  }
            }
      }
                  
      if ( sqlStr.Length > 0 ) {
            // update database
      }
}
Avatar of smooga

ASKER

"So you can create the grids in Page_Init or Page_Load
It will get Populated from viewstate data after Page_Load
Then you modify the database according to these data in OnButtonClick
Then you can recreate those grids according to the database in Page_Prerender."

But I would still be hitting the database before the viewstate loaded, right?  In order to create the grids without using the viewstate, I need to look up data in the database.  I'm trying to avoid hitting the database, overwriting that data with the viewstate, updating the database based on user input, and then hitting it again to recreate the controls based on the newly updated database.  Why load data from the database if it's only going to be immediately overwritten by the viewstate data?  Unless there's no other way to do it.  In which case, it would be more elegant to use client-side scripting to post the dropdown data to the server and then create the grids only once in Prerender.
ASKER CERTIFIED SOLUTION
Avatar of laotzi2000
laotzi2000

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of smooga

ASKER

b1xml,
    Ahh, I see what you're saying.  The Repeater will automatically persist the data unlike the Placeholder, right?  And I get the added benefit of having it spit out my multiple datagrids.  Terrific!  I think this is the right solution.

laotzi,
    Thanks for the link.  I'm going to use b1xml's solution though since it "kills 2 birds with one stone".

I want to give you both points... you were both more than helpful.  Is there a way to give 500 to both of you?  If not, are you ok with 250 each?
It doesn't matter.
I've learned quite a bit too. :)
Avatar of smooga

ASKER

Well, I tried to give you both 500.  Let me know if it worked.

Thanks guys.  Above and beyond :)