This is a migrated thread and some comments may be shown as answers.

Basic Window question

17 Answers 960 Views
Window
This is a migrated thread and some comments may be shown as answers.
GcM
Top achievements
Rank 1
GcM asked on 26 Oct 2007, 09:04 PM
I'm coming from a ASP .NET AJAX / Toolkit background and I'm used to developing windows that follow this pattern:

In the ASPX I would have an UpdatePanel in the body of the page and a ModalPopupExtender which would contain an UpdatePanel.  The event handler for the trigger on the page would populate values in the ModalPopupExtender's UpdatePanel and then display it via the Show() method.  The event handler for the Save button on the ModalPopupExtender would do any additional validation/persistence and, if successful, update values on the calling page's UpdatePanel and Hide() the dialog window. 

Is it possible to implement this pattern using the Prometheus Window and AjaxPanel/AjaxManager without having to write Javascript?

17 Answers, 1 is accepted

Sort by
0
Shaun Peet
Top achievements
Rank 2
answered on 29 Oct 2007, 02:47 AM
I think the tooltip may be better suited to follow that pattern (to write *no* javascript).

If you're up for writing a very small amount of javascript, you can do what you're trying to do by:

1) Having a script function that triggers an update on the parent page to refresh your data.
2) Open the window, loading into it an aspx page containing your data entry form - passing values into it using the QueryString.
3a) Use the onClientClose of the window to call the parent page's script to update the data
-- or --
3b) Create a javascript function in the window's aspx page that gets a reference to itself (ie. GetRadWindow()) - and then use that object to call the BrowserWindow.yourJSfunction() to call the parent page's script to update the data and then close the window.

I use this method - alot - and it works extremely well and fast.  The way I've got it setup I use a MasterPage for both the parent pages and the window pages - so the only thing that changes is the url of the window page.  I've also got a little javascript function in the window's master page that resizes the window based on the server-side code in the page_load event.

If interested, I can post the relevant code.
0
GcM
Top achievements
Rank 1
answered on 29 Oct 2007, 11:43 AM
Thanks a lot for the information.  I would definitely be interested in seeing the details of your implementation. I'm sure it would save me from making some mistakes as I come up to speed.  Thanks again.
0
Shaun Peet
Top achievements
Rank 2
answered on 29 Oct 2007, 04:41 PM
Ok, here comes all my trade secrets...

I will refer to the pages that displays the data as the "parent" pages and the pages that open within the window as "window" pages.  Both the parent pages and the window pages use a respective MasterPage.

The parent page's MasterPage has the following javascript function:

function postBackHF(HFID) { var hF = $get(HFID); if (hF) { hF.value = (new Date()).getTime(); __doPostBack(HFID,''); } }

Each parent page has an asp:HiddenField on it, located within an asp:UpdatePanel.  This function takes the client ID of that hidden field, and if found, changes the value of the hidden field.  The parent page then has server-side code that executes with the ValueChanged event for the hidden field.  For example, in the parent page markup:

<
asp:HiddenField ID="hfUC" runat="server" OnValueChanged="hfUC_ValueChanged" />

and in the parent page code (VB, in this case):

Protected
Sub hfUC_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs)
' UPDATE YOUR DATA HERE
End Sub

The real beauty of ths is the fact that you can segment your parent page into various asp:UpdatePanels, and then place an asp:HiddenField into each.  So long as the associated ClientID of the hidden field is passed into the postBackHF() function, only the corresponding part of the page will be updated.

Now, back to the parent pages MasterPage file.  There is also a javascript function as follows:

function
OpenModal(url) { var oManager = GetRadWindowManager(); var oWnd = oManager.GetWindowByName("rwForm"); oWnd.setUrl(url); oWnd.show(); return; }

In my experience, even though the RadWindowManager is no longer required for Prometheus, it still seems to work better this way, so in the parent page's MasterPage there is the following markup.

<
telerik:RadWindowManager runat="server" ID="rwmModal">
  <Windows>
    <telerik:RadWindow runat="server" ID="rwForm" />
  </Windows>
</telerik:RadWindowManager>

And that's all there is to the parent pages MasterPage file.

In order for the rest of this to make sense, I will provide a specific example of how I use this.  Namely, there will be a parent page that has a list of news articles that have been submitted to the site, and a corresponding "news article form".  So, each parent page has, in addition to the asp:UpdatePanel and asp:HiddenField as stated above, javascript functions that are called to open the window.  In this case, we will have two functions; one that opens the window in "New" mode, and one that opens the window in "edit" mode:

function
ShowNewArticleForm(HFID) { OpenModal('../Modals/Article.aspx?Mode=New&HFID=' + HFID); return false; }

function ShowEditArticleForm(ID, HFID) { OpenModal('../Modals/Article.aspx?ID=' + ID +'&HFID=' + HFID); return false; }

As you can see, both of these functions call the OpenModal() function that is on the MasterPage.

In order to trigger these functions, I have set the "onClick", or, in some cases, the "onDblCick" attributes of various HTML elements in the server-side code.  For example, I have a "Create New Article" button, which is actually a <span> element with runat="server" on the page.  In the Page_Load event:

spNew.Attributes.Add(
"onClick", "return ShowNewArticleForm('" & hfUC.ClientID & "')")

That takes care of opening the "new article" form.  The parent page in this case would have a list of articles, say, in a repeater called "rptList".  So, the server-side code would include:

Protected
Sub rptList_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptList.ItemDataBound
  Select Case e.Item.ItemType
    Case ListItemType.Item, ListItemType.AlternatingItem
    Dim div As HtmlGenericControl = e.Item.FindControl("nlItem")
    Dim ARTICLEid As Integer = e.Item.DataItem("ID")
    div.Attributes.Add(
"onDblClick", "ShowEditArticleForm(" & ARTICLEid & ",'" & hfUC.ClientID & "')")
  End Select
End Sub

So that takes care of opening the window.  The finishing touches involve creating the "Article.aspx" window page.  But first, here's the window MasterPage javascript functions:

function
get_RadWindow() { var oWindow = null; if (window.radWindow) { oWindow = window.radWindow; } else if (window.frameElement.radWindow) { oWindow = window.frameElement.radWindow; } return oWindow; }

Which gets a reference to the client-side window object.

function
CloseAndRebind(HFID) { get_RadWindow().BrowserWindow.postBackHF(HFID); get_RadWindow().Close(); }

Which calls the parent page postBackHF function, passing the hidden field's Client ID (which was brought in using the querystring of the window page), and then also closes the window.

function
JustRebind(HFID) { get_RadWindow().BrowserWindow.postBackHF(HFID); }

Which just calls the postBackHF function and leaves the window open.

function
JustClose() { get_RadWindow().Close(); }

Which just closes the window.

Using the last one is easy.  Simply set the onclick attribute (or the onClientClick property) to be "JustClose()".  I use this as a "Cancel" link in a window page.  The other two require that script is injected into the response after an event happens (for example, an "Update" link is clicked).  To make this seamless, I also include on the window MasterPage a RadAjaxManager as follows:

<
telerik:RadAjaxManager ID="ramModal" runat="server" />

So, let's say that the Article.aspx window page is a simple FormView control, that uses the ID of the article in the querystring to display the data in EditMode, or changes to InsertMode if the "Mode=New" parameters are in the querystring.  I can then wire up the FormView's ItemInserted and ItemUpdated events with the following code:

CType
(Master.FindControl("ramModal"), RadAjaxManager).ResponseScripts.Add("CloseAndRebind('" & Request.QueryString("HFID") & "')")

And voila!, the parent page is "refreshed" and the window is closed.

That's all there is to it (which may seem like alot, but 99% of this can be re-used for every page that you make), and the performance is really quite good.  The real beauty of this methodology is that the window pages can be heavily customized for the data that they are meant to handle.  For example, the Article.aspx page will probably have a r.a.d.Editor on it while other window pages could have calendars, input controls, etc. etc. etc.

In my futher attempts to minimize the amount of work I need to do in order to expand my projects, I have also created a javascript function that is added to the window pages MasterPage that resizes the window:

function
set_WindowSize(w,h) { var oWnd = get_RadWindow(); if (h > oWnd.BrowserWindow.getPaneHeight()) { h = oWnd.BrowserWindow.getPaneHeight() - 80; w = w + 30; } oWnd.set_Height(h); oWnd.set_Width(w); oWnd.center(); return; }

This calls a function on the parent page that I have setup that gets the height of the splitter pane that it happens to be in, and then checks that the height of the window doesn't exceed the height of the pane, and then sets the size of the window accordingly.  To make this work, I then add the following in the Page_Load for the window page:

Page.ClientScript.RegisterStartupScript(Type.GetType(
"System.String"), "SetSize", "set_WindowSize(700,500);", True)

Hope that helps!

0
GcM
Top achievements
Rank 1
answered on 30 Oct 2007, 07:16 PM
Wow!  Thanks for all your help.  I'll keep your trade secrets closely guarded. ;-)

Thanks again.
0
Shaun Peet
Top achievements
Rank 2
answered on 31 Oct 2007, 03:13 AM
No problem.  Let me know if you spot any improvements!
0
cserold
Top achievements
Rank 1
answered on 31 Oct 2007, 12:09 PM
This post was extremely helpful.  Shaun, can you offer any guidance for best practices of doing standard ASP.NET forms validation inside a RadWindow?  Basically, I need to perform the validation on in a server-side event in the window page and, if the user is validated successfully, close the window page and perform the "RedirectFromLoginPage" on the parent page.  Does that make sense? Thanks Shaun.
0
Shaun Peet
Top achievements
Rank 2
answered on 31 Oct 2007, 02:23 PM
It sort of makes sense; I think.  I'm assuming you want to use the Window to have a "Login.aspx" style page, and the close the Window upon logging in and then redirecting somewhere else.

Using the "normal" methodology for logging in, a "Login" link posts-back to the server, calling the FormsAuthentication.RedirectToLoginPage() method.  So you then end up on the login page which also has a "ReturnUrl=" parameter in the querystring.  Upon successful login, ASP.NET uses that parameter to go back to the page where the "Login" link was clicked - UNLESS - you have manually told the asp:Login control to go somewhere else upon logging in.

So back to your scenario then.  If using the default path as above - where the user is returned to the "original" page; you wouldn't need to redirect to a different page; you just need to reload the current parent page.  However, if you always want to go to a different page upon successful login, then you can just do the Response.Redirect() to the desired page.

This is where it gets tricky.  My method above shows how you can trigger a postback on the parent page and then close the window page.  I'm not exactly sure what the effects would be if you reversed the order - closing the window first and then posting back.  My initial testing shows that this might work.  So, instead of:

function CloseAndRebind(HFID) { get_RadWindow().BrowserWindow.postBackHF(HFID); get_RadWindow().Close(); }

you would have:

function
CloseAndRebind(HFID) { get_RadWindow().Close(); get_RadWindow().BrowserWindow.postBackHF(HFID); }

So, upon posting back the parent page you simply call Response.Redirect(Request.Url.ToString) or Response.Redirect("SomeOtherPage.aspx") as necessary.  Just for fun, I tested whether or not you can get away with doing a Response.Redirect and my quick testing revealed that yes, you can.

Hope that helps.

0
cserold
Top achievements
Rank 1
answered on 01 Nov 2007, 03:35 AM
Shaun,
I wanted to thank you again for going above and beyond with the details of post.  The methodology you outlined in this thread is SOOOO helpful.

Thanks again,
Craig
0
Shaun Peet
Top achievements
Rank 2
answered on 01 Nov 2007, 11:13 PM
No problem, I'm glad I could help.  Maybe if the telerik guys get a chance someday they can have a look at the code and see if there's any other improvements that can be made.  My current code has gone through the polisher a few times already ;)
0
Georgi Tunev
Telerik team
answered on 02 Nov 2007, 11:26 AM
Hello Shaun,

Your code looks very good and for now we cannot suggest any significant improvements on it. On the behalf of Telerik's staff  I would like to thank you for sharing it in the forums. 

If it is not a problem for you, I invite you to prepare a small sample project which uses your approach and to upload it in the Code Library section of our site - I am sure it will be very useful for the whole community




Have a great weekend,
Georgi Tunev
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Shaun Peet
Top achievements
Rank 2
answered on 02 Nov 2007, 11:51 AM
I started that process last night and will hopefully have something by next week.
0
Georgi Tunev
Telerik team
answered on 02 Nov 2007, 02:08 PM
It is great to hear that Shaun :)


Once again, thank you for your dedication and efforts.




Best wishes,
Georgi Tunev
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Shaun Peet
Top achievements
Rank 2
answered on 13 Dec 2007, 05:10 AM
0
Georgi Tunev
Telerik team
answered on 13 Dec 2007, 11:55 AM
Hi Shaun,

Thank you for the article - I am sure the community will benefit from it.



Sincerely yours,
Georgi Tunev
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Chris
Top achievements
Rank 1
answered on 10 Jan 2009, 07:03 AM
I was looking for a standard way to handle the editing of data with a popup window when I came across this "oldie but a goodie" thread.  I downloaded and played with the Code Library that Shaun provided.

I came across an issue when I had my "List" be in the form of a RadGrid.  I believe the issue is related to the data binding but I can't seem to figure it out.  Here is my setup:

List Page:
A basic RadGrid inside of RadAjaxPanel (and I have tried a regular UpdatePanel).  In side of this Panel I have included the Hidden field.  In the code behind on the Page_Load event, I have the standard "hook up the grid's datasource if it is not a postback" code.  In the Hidden field's OnValueChanged event, I have the code to rebind the grid when the popup window closed with a rebind.

When I run the page and trigger the popup, the window displays and I am able to update my data.  When I click the Update button, the data is saved and the popup closes. 

Here is were the problem shows up.  On the postback triggered by the closing popup, the OnValueChanged event is never fired.  If I take a peek with Firebug, I see this error: "There was a problem extracting DataKeyValues from the DataSource. Please ensure that DataKeyNames are specified correctly and all fields specified exist in the DataSource".

This error kind of makes sense since the OnValueChanged event never fired, the RadGrid was never data bound.  For some reason it looks like the RadGrid is looking for data before the Hidden fields event is fired.

Shuan, have you seen this behavior and if so, how do you deal with it? 

Thanks

BTW, I am using the 2008 Q3 release of the Rad Asp.Net Ajax tools
0
Georgi Tunev
Telerik team
answered on 10 Jan 2009, 02:20 PM
Hello Chris,

At this point we cannot say what the reason for the problem might be, but I would suggest to check the following help article and ensure that your setup follows the guidelines shown there:
http://www.telerik.com/help/aspnet-ajax/grdextractkeyvaluesclientside.html

If you still experience problems after that, it will be best to open a support ticket and send us a small sample project where this issue can be reproduced. We will check it and do our best to help.


Best wishes,
Georgi Tunev
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Hossein Jabbarzadeh
Top achievements
Rank 1
answered on 07 Jan 2011, 05:25 PM
Thanks Shaun, It saves me a lot of time. 
Really, really Appreciate it .

Thanks
Hossein
Tags
Window
Asked by
GcM
Top achievements
Rank 1
Answers by
Shaun Peet
Top achievements
Rank 2
GcM
Top achievements
Rank 1
cserold
Top achievements
Rank 1
Georgi Tunev
Telerik team
Chris
Top achievements
Rank 1
Hossein Jabbarzadeh
Top achievements
Rank 1
Share this question
or