Καλησπέρα παιδιά ...
Σήμερα στη δουλειά, μου ζητήθηκε το εξής:
Θα θέλαμε οι σελίδες μας, απο ένα client-side script να κάνουν postback, και να γίνεται raise ένα event στο server. Αυτό ήταν απόρροια μιας κατάστασης, όπου ένα modal dialog χρειαζόταν να κάνει refresh (
το λέμε και reload εδω) τη σελίδα η οποία το άνοιξε, και για διάφορους λόγους ένα απλό document.location.reload() δεν εξυπηρετούσε τους σκοπούς μας.
Μετα απο κάποια ώρα που χρειάστηκα να "πιάσω" (
είμαι και λίγο αργός ..
) νοηματικά το ζητούμενο, το έκανα τελικά, και είπα να μοιραστώ την
εμπειρία γιατί .. είναι αν μη τι άλλο, έστω και ελάχιστα ενδιαφέρον :)
Λοιπόν ... το framework μας παρέχει τη δυνατότητα να κάνουμε generate ένα τέτοιο script, χρησιμοποιώντας τη μέθοδο
GetPostBackEventReference(Control ctrl) : string
GetPostBackEventReference(Control ctrl, string argument) : string
Η μέθοδος "
γυρίζει" ένα string το οποίο περιέχει τον κώδικα σε JavaScript που κάνει αυτή τη δουλειά ... οκ, σε αυτό το σημείο σκέφτηκα εγώ ... "
εμμμ ... οκ .. και τώρα .. πως πιάνω εγώ αυτό το event;;; Και τί είναι αυτές οι παράμετροι τύπου Control & string;;;" ... έλα παναγία μου ..
Λοιπόν, στο framework κάπου, υπάρχει το interface IPostBackEventHandler. Αυτό, ορίζει μια μοναδική μέθοδο:
RaisePostBackEvent(string eventArgument) : void
Ωραία, σκέφτηκα. 'Αρα, αν κάνω τη σελίδα μου να υλοποιεί αυτό το
interface, και βάλω τον JavaScript κώδικα απο παραπάνω σ'ενα button (
ή τελος πάντων τον καλέσω κάπως ... ), θα κάνω τη δουλειά μου και θα καλεστεί η RaisePostBackEvent όμορφα και ωραία.
Λάθος ! :D
Το παραπάνω αρνήθηκε να δουλέψει. (
Αργότερα έμαθα το λόγο, τον οποίο θα σας πώ στο τέλος :) )
Οπότε, αποφάσισα την πεπάτημένη του ... workaround. Έγραψα μια μικρή
κλάσση, η οποία κάνει inherit το Control, και implement το
IPostBackHandler:
class WebClientPostBackHandler
: Control, IPostBackEventHandler {
private allWebBasePage _parent = null;
public allWebClientPostBackHandler(WebBasePage
parent){
this._parent = parent;
}
#region IPostBackEventHandler Members
public void
RaisePostBackEvent(string eventArgument)
{
if(_parent!=null)
_parent.PageReloading();
}
#endregion
}
Όλες μου οι σελίδες είανι derived (
έτσι κι αλλιώς) απο την
WebBasePage, οπότε ήταν εύκολο για μένα να προσθέσω στην κλάσση τη
μέθοδο PageReloading ως virtual, έτσι ώστε να την υλοποιήσω όταν
χρειάζεται.
/// <summary>
/// Called whenever
the page is 'refreshed' using client-side scripting (awep_formReload() method)
/// </summary>
protected virtual void
PageReloading(){
//
Do nothing.
//Response.Write("RELOADED!!!");
}
Αμέσως μετά, πρόσθεσα ένα member variable στην WebBasePage, τύπου
WebClientPostBackHandler, την οποία κάνω instantiate στον constructor:
private WebClientPostBackHandler
_clientPostBackHandler = null;
public WebBasePage() : base() {
//
Register the event handler
_clientPostBackHandler = new WebClientPostBackHandler(this);
}
Δεν ξεχνώ να προσθέσω αυτό το μικρό Control στο Control tree της σελίδας μου στην OnInit(...) :
this.Controls.Add(this._clientPostBackHandler);
Και τέλος, να κάνω register το script το οποίο κάνει όλη αυτή τη μαγεία πραγματικότητα:
private void
RegisterReloadScript(){
if(!this.IsClientScriptBlockRegistered(CLIENTSCRIPTKEY_Reload))
{
string strClientReloadScript = this.GetPostBackEventReference(this._clientPostBackHandler);
System.Text.StringBuilder
stb = new System.Text.StringBuilder();
stb.Append("<script
language=\"javascript\">");
stb.Append("function formReload() { ");
stb.Append(strClientReloadScript);
stb.Append("}");
stb.Append("</script>");
string strClientScript = stb.ToString();
this.RegisterClientScriptBlock(CLIENTSCRIPTKEY_Reload,
strClientScript);
}
}
... και καλώ την παραπάνω μέθοδο στην onLoad(EventArgs e). H σελίδα που
παράγεται, περιέχει τη JavaScript function formReload(), όταν καλείται
η οποία, η σελίδα γίνεται post back, οι event handlers παίρνουν φωτιά,
και τελικά καλείται η PageReloading() στο server-side κώδικα της
εκάστοτε σελίδας :)
Πολύ καλό βράδυ μας !!!
Υ.Γ. ... όπως ανέφερα παραπάνω, αν κάνετε τη σελίδα σας να υλοποιεί τον
IPostBackEventHandler, η RaisePostBackEvent(...) δε θα καλεστεί ποτέ.
Αυτό συμβαίνει διότι η Page κάνει implement το interface
IPostBackDataEventHandler, του οποίου η υλοποίηση "κρύβει" τη μέθοδο
του "απλού" IPostBackEventHandler ... (
κι επίσης ... σκέφτηκα να
μη μπλέξω με ένα τοσο "ευαίσθητο" μέρος της Page - είναι η
μέθοδος που καλείται σε κάθε postback και παίρνει/δίνει/πείτε το όπως
θέλετε τα data απ'τα controls της φόρμας στο Control tree της σελίδας,
οπότε .. καλύτερα να μην τη χαλάμε, να'μαστε και σίγουροι :D )
Angel
O:]