Mostanában divat azon vitatkozni, hogy az ASP.NET vagy a Silverlight-e a jövő webfejlesztő technológiája. Különösen az utóbbi hívei között vannak olyanok, akik szeretik azt hinni, hogy kis kedvencük minden helyzetben tökéletes választás. Szerintem a két technológiát együtt fogjuk használni a jövőben: amit nem lehet vagy nem célszerű a böngészőben megoldani, ott fogunk a böngésző bővítményhez folyamodni. Ehhez persze nélkülözhetetlen, hogy a két világ tudjon egymással kommunikálni.
Silverlight alkalmazás inicializálása ASP.NET-ből
Egy Silverlightos alkalmazásnak induláskor adatokat adhatunk át az initParams paraméterben. Egyetlen stringben, vesszővel elválasztva kell felsorolnunk az átadandó kulcs-érték párokat.
HTML:
<object data="data:application/x-silverlight-2," ...>
<param name="source" value="ClientBin/SilverlightApplet.xap"/>
<param name="initParams" value="p1=Első paraméter,p2=Második paraméter" />
...
</object>
ASP.NET-ben a beágyazó asp:Silverlight vezérlő InitParameters tulajdonságát kell használnunk akár code behindból, akár ASPX markupból:
<asp:Silverlight ID="slPlugin" runat="server" Source="~/ClientBin/SilverlightApplet.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%"
InitParameters="p1=Első paraméter,p2=Második paraméter" />
Az így átadott paraméterek Silverlightban az App.xaml.cs fájlban lévő Application_Startup metódus StartupEventArgs e paraméterében érkeznek meg egy szótár típusú változóban. Ha nem csak itt akarjuk elérni, akkor szerintem érdemes kitenni statikus változóba:
// Silverlight:
public partial class App : Application
{
internal static IDictionary<string, string> InitParams;
private void Application_Startup( object sender, StartupEventArgs e )
{
App.InitParams = e.InitParams;
this.RootVisual = new Page();
}
}
Ez persze bárhonnan elérhető a Silverlight alkalmazáson belül:
// Silverlight: A bemenő paramétereket vesszővel kell elválasztani, különben KeyNotFoundException jön.
this.lblInitParams.Text = String.Format( CultureInfo.InvariantCulture,
"Param1={0}, Param2={1}", App.InitParams[ "p1" ], App.InitParams[ "p2" ] );
Érték átadása a weboldalról
Az ASP.NET és a Silverlight együttélésének a kulcsa a Silverlight HTML Bridge nevű komponense, aminek segítségével felügyelt kódból érhetjük el a böngészőben futó oldalt, illetve a felügyelt kódunk bizonyos részeit tehetjük böngészőből elérhetővé. Ahhoz, hogy a weboldalról adatot tudjunk átadni egy Silverlight alkalmazásnak, egy felügyelt metódust kell publikálnunk, melyet majd JavaScriptből hívunk meg. A kiválasztott metódus elé a [ScriptableMember] attribútumot kell biggyesztenünk. Ha a metódust más néven akarjuk szkriptből meghívni, használhatjuk az attribútum ScriptAlias tulajdonságát. Ha egy osztály összes metódusát publikálni szeretnénk, akkor az osztály elé tehetjük a [ScriptableType] attribútumot.
// Silverlight
// [ScriptableType]
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject( "MyScriptableType", this );
}
[ScriptableMember]
public string SayHello( string name )
{
this.lblMessageIn.Text = name;
return "Szia " + name;
}
}
A következő lépés a HtmlPage.RegisterScriptableObject meghívása. Az első paraméterben tetszőleges sztringet megadhatunk, ilyen néven lesz elérhető a második paraméterben megadott objektumunk JavaScriptből.
A példában egy HTML szövegdoboz értékét adjuk át gombnyomásra a fenti SayHello metódusnak, ami az slPlugin azonosítójú asp:Silverlight vezérlőben fut:
<!-- ASPX -->
<asp:ScriptManager runat="server" />
<input type="text" id="txtName" />
<input type="button" value="Küldés" onclick="sendToSilverlight()" />
<script type="text/javascript" language="javascript">
function sendToSilverlight()
{
var slPlugin = $get( '<%= this.slPlugin.ClientID %>' );
var txtName = $get( 'txtName' );
var result = slPlugin.Content.MyScriptableType.SayHello( txtName.value );
alert( 'Válasz: ' + result );
}
</script>
A JavaScript írásakor ne várjunk az IntelliSensre, nem lesz.
Érték átadása a weboldalnak
Silverlightból adhatunk át adatokat a weboldalnak, a HTML Bridge segítségével ugyanis gyakorlatilag a teljes DOM-ot kezelhetjük felügyelt kódból. (Na ezt kellene valakinek megírnia egy kicsit típusosabban ASP.NET-ben…) Arra kell csak figyelni, hogy a Silverlight pluginon vagy az őt tartalmazó div elemen ne legyen display:none vagy visibility:hidden. Szépen is néznénk ki, ha láthatatlan vezérlők rángathatnák a weboldalunkat 🙂
Íme az ASPX oldalunknak az a része, amely fogadni fogja az adatot a Silverlight alkalmazástól:
Fogadott: <span id="lblName">(még nem jött semmi)</span>
Silverlight oldalon faragtam egy mini űrlapot:
<StackPanel Orientation="Horizontal">
<TextBlock Text="Küldendő üzenet: " FontWeight="Bold" VerticalAlignment="Center" />
<TextBox x:Name="txtMessageOut" Width="100" />
<Button x:Name="btnSend" Content="Küldés" Click="btnSend_Click" />
</StackPanel>
A lényeg persze a gomb eseménykezelője:
// Silverlight
private void btnSend_Click( object sender, RoutedEventArgs e )
{
HtmlDocument doc = HtmlPage.Document;
HtmlElement lblName = doc.GetElementById( "lblName" );
lblName.SetAttribute( "innerHTML", this.txtMessageOut.Text );
}
Weboldal esemény kezelése Silverlightban
Arra is van lehetőségünk, hogy felügyelt kódban kezeljük egy HTML DOM objektum valamely eseményét, ráadásul ehhez nem kell JavaScriptet írni. Készíthetünk például egy combo boxot a weblapunkra:
<!-- HTML / ASPX -->
<select id="selWelcome">
<option>Szia</option>
<option>Helló</option>
<option>Üdv</option>
</select>
A select objektumnak van egy changed eseménye, amire feliratkozhatunk Silverlightból:
// Silverlight: feliratkozás weblap esem?nyre
HtmlDocument doc = HtmlPage.Document;
HtmlElement selWelcome = doc.GetElementById( "selWelcome" );
selWelcome.AttachEvent( "onchange", new EventHandler<HtmlEventArgs>( this.OnWelcomeChanged ) );
Sajnos itt sem lesz IntelliSense az eseménykezelő megírásához, ezért jó tudni, hogy létezik egy HtmlEventArgs paraméter típus:
private void OnWelcomeChanged( object sender, HtmlEventArgs e )
{
HtmlElement selWelcome = sender as HtmlElement;
string selection = String.Empty;
foreach( HtmlElement option in selWelcome.Children )
{
object selectedProperty = option.GetProperty( "selected" );
if( selectedProperty != null )
{
if( selectedProperty.ToString().Equals( "true", StringComparison.OrdinalIgnoreCase ) )
{
selection = option.GetProperty( "innerHTML" ).ToString();
}
}
}
MessageBox.Show( "Ezt választottad az oldalon: " + selection );
}
A fenti kódból talán látszik, hogy a HTML Bridge az összes HTML elemet egyetlen HtmlElement osztályra képezi le. Ez persze nem rossz, de most éppen kicsit nehézkes megkeresni a kiválasztott gyermekelemet. Persze bevethetünk egy kis LINQ-et 🙂
string selection = ( from HtmlElement option in selWelcome.Children
let o = option.GetProperty( "selected" )
where
p != null &&
p.ToString().Equals( "true", StringComparison.OrdinalIgnoreCase )
select option.GetProperty( "innerHTML" ).ToString()
).First();
A felhasznált osztályok a System.Windows.Browser névtérben találhatóak. Érdemes ott körülnézni, van ott még más hasznos típus is…
A cikkhez tartozó forráskód letölthető: HtmlBridgeSampleSolution.zip (549 kB)