Professional Documents
Culture Documents
Silverlight is a web based technology, launched by Microsoft in April 2007. Silverlight is considered as a competitor to Adobes Flash. Silverlight applications are delivered to browsers in a text-based markup language called XAML. One important difference between Flash and XAML is, Flash is a compiled application where as XAML is text based. Search engines can analyze and index such content, which is a huge benefit for webmasters. For regular internet users, Silverlight is a browser plug-in that supports video, audio and animations. For web developers, Silverlight offers much more. Silverlight supports video and audio files without need of much programming. It allows them to handle events from web pages (like handle start/end of video playing etc)
browser based internet applications. WPF is a Microsoft technology meant for developing enhanced graphics applications for desktop platform. In addition, WPF applications can be hosted on web browsers which offers rich graphics features for web applications. Web Browser Appliactions (WBA) developed on WPF technology uses XAML to host user interface for browser applications. XAML stands for eXtended Application Markup Language which is a new declarative programming model from Microsoft. XAML files are hosted as descrete files in the Web server, but are downloaded to the browsers and converted to user interface by the .NET runtime in the client browsers. WPF runs on .NET runtime and developers can take advantage of the rich .NET Framework and WPF libraries to build really cool windows applications. WPF supports 3-D graphics, complex animations, hardware acceleration etc.
If you are using Visual Studio, you can download the Silverlight development tools from here. This download include the Service pack1 for VS.NET and the Silverlight SDK. Which tool to use - Expression Studio or Visual Studio ? If your Silverlight application include just graphics adn visual elements, then you can use Expression Studio. However, if you are a programmer and if your Silverlight application include programming logic, then you might want to choose Visual Studio.
What is XAML ?
XAML stands for eXtended Application Markup Language. XAML contain XML that is used to declaratively specify the user interface for Silverlight or WPF applications. For example, if you need to display a rectangle, this is the XAML you need to use:
<Canvas Width="500" Height="500" Background="White"> <Rectangle Canvas.Left="75" Canvas.Top="90" Fill="red" Width="100" Height="100" /> </Canvas>
When the above xaml is executed, it will display a rectangle filled with red color. You may notice is that XAML is very similar to HTML in nature.
We need a web page to host the Silverlight components that we develop. Visual Studio makes this job easier in the next step by prompting you to automatically create a website. Choose the options as shown in the attachment.
You are ready to rock ! Just press OK and Visual Studio will create 2 projects and a bunch of files for you. We will analyze some of the files created by Visual Studio in the next chapter.
We will analyse some of the files. AppManifest.xml This file defines the assemblies that are deployed to the client applications.
TagPrefix="asp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;"> <head runat="server"> <title>Test Page For MySilverlightApp</title> </head> <body style="height:100%;margin:0;"> <form id="form1" runat="server" style="height:100%;"> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <div style="height:100%;"> <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/MySilverlightApp.xap" MinimumVersion="2.0.30523" Width="100%" Height="100%" /> </div> </form> </body> </html>
Most of the stuff above look familiar to ASP.NET developers. Some of the lines that need some attention are:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/MySilverlightApp.xap" MinimumVersion="2.0.30523" Width="100%" Height="100%" />
The second line defines the Silverlight control to be hosted in the web page. The attribute "Source" defines the .xap file to be used by the web page. This .xap file contains the XAML and code from your .xaml files and will be executed by the Silverlight plugin. In the current sample, you have just one xaml file called Page.xaml. When you compile the solution, this file is compiled into a special file (MySilverlightApp.xap) with the extension .xap.
What is app.xaml ?
App.xaml is a file used by Silverlight applications to declare shared resources like brushes, various style objects etc. Also, the code behind file of app.xaml is used to handle global application level events like Application_Startup, Application_Exit and Application_UnhandledException. (Similar to Global.asax file for ASP.NET applications) When Visual Studio creates the app.xaml file automatically, it creates few event handlers with some default code. You can change the code appropriately.
private void Application_Startup(object sender, StartupEventArgs e) { }
private void Application_Exit(object sender, EventArgs e) { } private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { }
For ASP.NET developers, the above code will look familiar. This is similar to the aplication level event handlers in Global.asax.
Page.xaml file
When you create a Silverlight project using Visual Studio 2008, it creates a default xaml file called "Page.xaml". This is just a dummy start page created by Visual Studio and it does not contain any visible UI elements. The default content of the page.xaml file looks like this:
<UserControl x:Class="MySilverlightApp.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> </Grid> </UserControl>
The above code shows a user control and a Grid control. The UserControl is a high level control that holds all other UI elements in a xaml file. The Grid control is used as a layout panel and it can hold other UI elements. All UI elements in a .xaml control must be placed within a layout panel. There 3 different types of layout panels available in Silverlight 2.0. You will learn more about layout controls in a later chapter. When you compile your Silverlight Application project, it will compile all .xaml files and various other resources in to a single assembly file. This assembly file will have the extension .xap and will have the same file name as your project name. To place your Silverlight control in a web page, you must refer to this .xap file in your web page. When the .xap file is referred in a web page, the default .xaml page will be shown. Based on user actions, you may open or close various .xaml files included in your .xap assembly (Silverlight Application project).
You can swap the position of the code and preview by pressing the icon with 2 arrows in the middle of the screen (between the tabs "XAML" and "Design". Also, you can use the icons on the right end between the code and design panes to change the position of the code pane and design preview.
One or more Silverlight Applications can be placed in a web page using xaml tags as shown below:
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/MySilverlightApp.xap" Width="300" Height="300" />
In the above tag, the attribute "source" represents the name of the xap file which is the compiled output of the Silverlight project. The .xap files contains the compiled version of all .xaml files included in the Silverlight Application project. When you compile the Silverlight Application project, it will be compiled to an assembly with the extension .xap. For example, if your Silverlight project name is "MySilverlightControl", when compiled, it will produce the assembly MySilverlightControl.xap Each Silverlight project can have multiple .xaml files. Each .xaml file is like a page or form by itself. When you place a Silverlight Application in a web page, only one .xaml control will be visible at a time. Based on various user actions, you may dynamically open various .xaml pages (Just like you open forms in a windows application).
After you change the value here, compile the application and run. When the web page is opened, you can see that the new .xaml control is displayed in the web page.
You can change the above line to the class name of any oher xaml file to open that file by default. Another scenario is, you may want to open different xaml files from the default xaml page. For example, consider that you have a xaml control that prompt user to enter login information. After the login credentials are validated, you may want to redirect to another xaml file when the user click the "Submit" button. This can be done by setting the "Content" property of the xaml page.
private void SubmitButton_Click(object sender, RoutedEventArgs e) { this.Content = new NewXamlPage(); }
The above code shows how to set the "Content" property of the xaml control in the button click event handler. When the user click on the submit button, the new xaml file (NewXamlpage) will be opened and original xaml file will be recycled.
the same .xap file from different web pages. You can do this by passing the xaml file name or some other kind of identification using InitParameters property of the Silverlight control. This property can be set to the Silverlight control from the web page. The value set from web page will be read by the Silverlight control and appropriate xaml page will be opened. To demonstrate this, let us create a sample Silverlight project with the name "OpenSpecificXaml". (You can read the steps to create a new Silverlight project.) After you compile and build your project, place the Silverlight control in your web page as shown below:
<asp:Silverlight InitParameters="PageName=Page1" ID="Xaml1" runat="server" Source="~/ClientBin/OpenSpecificXaml.xap" MinimumVersion="2.0.30923.0" Width="100%" Height="100%" />
Here we are setting the property "InitParameters" with a key-value pair indicating which xaml page we want to open by default. Now, we will read this property in the App.xaml file and set the appropriate page to the Application.RootVisual property. Here is the sample code to use in the App.xaml.cs to achieve this:
private void Application_Startup(object sender, StartupEventArgs e) { IDictionary parameters = e.InitParams; if (parameters == null) { // No parameter passed.. open the default xaml this.RootVisual = new DefaultPage(); } else if (parameters["PageName"] == "Page1") { this.RootVisual = new Page1(); } else if (parameters["PageName"] == "Page2") { this.RootVisual = new Page2(); } else { // Open the default xaml this.RootVisual = new DefaultPage();
} }
The above xaml tags defines a rectangle, filled with green color, of size 100x100 pixels. The rectangle will be placed 25 pixels from the left of the Canvas and 40 pixels from the top of the Canvas. The below example shows 3 rectangles overlapped each other:
<Canvas Width="500" Height="500" Background="White"> <Rectangle Canvas.Left="25" Canvas.Top="40" Fill="green" Width="100" Height="100" /> <Rectangle Canvas.Left="50" Canvas.Top="65" Fill="yellow" Width="100" Height="100" /> <Rectangle Canvas.Left="75" Canvas.Top="90" Fill="red" Width="100" Height="100" /> </Canvas>
Image.stretch Property The Stretch attribute can have the following values: 1. None This will do no modification on the size of the image. If the image size is more than the size of the container, then the image will be cut to fit in the container.
2. Fill In this case, the image will be expanded to fill the region of the container. The aspect ratio (proportion of width and height) will not be maintained. 3. Uniform This is the default value. In this case, the image will be resized to fit the container, but the aspect ratio will be maintained. So, there may be blank space in the container depending on the width and height of the image and container. 4. UniformToFill In this case, the image will be resized and will fill the container, but aspect ratio will be maintained by trimming some portion of the image if required. Width and Height properties The width and height properties of the image can be used to override the stretch property. If width and height properties are specified, then Stretch property will be ignored. Image.Clip property The clip property of Image control can be used in Silverlight to make certain portion of the image visible and hide some part of it. See an example of how to display an image in a elliptical form:
<Grid x:Name="Layout" Width="200" Height="220" Background="YELLOW" > <Image x:Name="MyImage" Source=" Images/AppleTree.png" Stretch="Fill"> <Image.Clip> <EllipseGeometry x:Name="Ellipse" RadiusX="100" RadiusY="100" Center="100,110"/> </Image.Clip> </Image> </Grid>
In the above code, a Border control is placed in the Canvas. The most important code to note is:
MouseLeftButtonDown="border1_MouseLeftButtonDown" MouseLeftButtonUp="border1_MouseLeftButtonUp" MouseMove="border1_MouseMove"
The above lines define 3 events that we like to handle. As the name indicates, we are handling the mouse button down, mouse button up and mouse move events for the left mouse.
In the code behind, when the left button is pressed, we will set a global variable to indicate that user has started moving. In the mouse move event, we will get the current location of the mouse pointer and then set the new position for the border control. When the left mouse button is released, we will reset the global variable so that we will not move the object any more. See the code for the code behind class:
public partial class Page : UserControl { // Global variable to indicate if user has clicked border // and started/stopped moving. private bool moving = false; private double offSetX; private double offSetY; public Page() { InitializeComponent(); } private void border1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // Left mouse button clicked within border. start moving. moving = true; Point offset = e.GetPosition(border1); offSetX = offset.X; offSetY = offset.Y; } private void border1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // Left mouse button release. Stop moving. moving = false; } private void border1_MouseMove(object sender, MouseEventArgs e) { if (moving) { // Get the new mouse pointer position Canvas parent = (Canvas)this.border1.Parent; Point p = e.GetPosition(parent); double x = p.X - offSetX; double y = p.Y - offSetY; // Set the new position for the border control. this.border1.SetValue(Canvas.LeftProperty, x); this.border1.SetValue(Canvas.TopProperty, y); } } }
You can set this property from the code behind file of your ASPX page as well. Example - Set InitParameters property from the code behind file:
Xaml1.InitParameters = "City=Houston,State=Texas,Country=USA";
How to retrieve the InitParameters value ? The value you pass to a Silverlight control through the InitParameters property can be retrieved from the Application_Startup even handler in the App.xaml page.
private void Application_Startup(object sender, StartupEventArgs e) { IDictionary parameters = e.InitParams; this.RootVisual = new Page1();
Now, in most cases, you may want to pass this value to the xaml page itself instead of doing
anything with in it the App.xaml. Pass parameters from App.xaml to other pages To pass the parameters from the App.xaml pages to other pages, you must modify the constructor of xaml page class to accept parameters.
private IDictionary<string, string> parameters = null; public Page1() { InitializeComponent(); } public Page1(IDictionary<string, string> p) { this.parameters = p; InitializeComponent(); }
The above sample shows an additional constructor added which takes a parameter of type IDictionary and then sets the value to a member variable. Now go back to your App.xaml and pass the parameters to the page:
private void Application_Startup(object sender, StartupEventArgs e) { IDictionary parameters = e.InitParams; this.RootVisual = new Page1(parameters);
Use the IDictionary parameter values in the XAML pages If you have followed the above steps correctly, you should be able to access the IDictionary values in your XAML page.
textblock1.Text = this.parameters["City"];
In the code behind file for your page1.xaml, you can set the Text for the textblock1 control as shown below:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { textblock1.Text = parameters["City"]; }
In the next screen, choose the option "Add a new web to the solution for hosting the control".
Right click on the web project in the Solution Explorer and select "Add New Item". Select the category "Silverlight" from the left panel in the dialog box. From the right panel, select the template "Silverlight-enabled WCF Service" Choose the default name "Service1.svc" and press the "Add" button. (The current beta version of Visual Studio may show you an error object reference not set to an instance .... Ignore this error and proceed.) You can see the below code:
[ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode =
Explaining the concepts of WCF is beyond the scope of this tutorial. However, I just want to point out 2 things here:
[ServiceContract(Namespace = "")]
- This attribute above the class name indicates that this class is a WCF service.
[OperationContract]
- This attribute above the method name indicates that this method can be called from a WCF client. Let us add a new method to our WCF service class, decorated with the [OperationContract] attribute. Add a method as shown below:
[OperationContract] public string GetName() { return "John"; }
As you can see, it is a simple method which returns a hard coded name. Open your solution explorer. Right click on the file "Service1.svc" and select "Set as Startup Page". Now run the application by pressing Ctrl + F5 (or, using the menu "Debug" > "Start Without Debugging") The browser will be opened and Service1 meta data will be displayed. Ignore the content in the page, but copy the URL from the browser. The URL will look something like this:
http://localhost:1873/Service1.svc
The port number may be different in your case, but that is OK. Return to your Solution Explorer in Visual Studio. Right click on your Silverlight project (not web project) and select "Add Service Reference". In the field for Address, specify the URL you copied from the browser and press "GO". In the bottom left, change the namespace to "MySampleService". You should see a screen like this:
Press "OK" to add the service reference. Now you can call our WCF service from the Silverlight client. To test this, follow these steps: 1. Open the Page1.xaml file and add a textblock to display the string returned from the WCF method call. 2. Add an event handler for the "Loaded" event of the UserControl. Complete code from Page1.xaml is given below:
<UserControl x:Class="Silverlight_With_WCF.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300" Loaded="UserControl_Loaded"> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock x:Name="textblock1" Width="200" Height="30"></TextBlock> </Grid> </UserControl>
Now go to the code behind file (Page1.xaml.cs) and add the WCF service call as shown below:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { MySampleService.Service1Client client = new MySampleService.Service1Client(); client.GetNameCompleted += new EventHandler(client_GetNameCompleted);
Open the web project in Solution Explorer and set the Silverlight test page as the startup page. Now run the project. You can see that the WCF service is called from Silverlight client and the result is displayed in the browser. (In our sample, the result from the WCF call is the name "John" and this name will be displayed in the screen). You can download a sample project for this tutorial.
Create a new Silverlight project with a web project to host the Silverlight control. Steps: 1. Open Visual Studio and select the menu "File" > "New" > "Project" 2. Select the Project Type as "Silverlight" under your favorite language and choose the template "Silverlight Application". I have selected Visual C# as the tutorials here. I have named my project as "AccessSessionFromSilverlight" and have selected the option "Create directory for solution" so that all my project files are organized within a folder structure. 3. In the next screen, choose the option "Add a new web to the solution for hosting the control". 4. After Visual Studio creates the solution, right click on the web project in the Solution Explorer and select "Add New Item". 5. Select the category "Silverlight" from the left panel in the dialog box. From the right panel, select the template "Silverlight-enabled WCF Service" 6. Choose the default name "Service1.svc" and press the "Add" button. 7. You can see the below code:
[ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class Service1 { [OperationContract] public void DoWork() { return; } }
8. Open your solution explorer. Right click on the file "Service1.svc" and select "Set as Startup Page".
9. Now run the application by pressing Ctrl + F5 (or, using the menu "Debug" > "Start Without Debugging") The browser will be opened and Service1 meta data will be displayed. Ignore the content in the page, but copy the URL from the browser. The URL will look something like this:
http://localhost:1873/Service1.svc
The port number may be different in your case, but that is OK. 10. Return to your Solution Explorer in Visual Studio. Right click on your Silverlight project (not web project) and select "Add Service Reference". In the field for Address, specify the URL you copied from the browser and press "GO". In the bottom left, change the namespace to "MySampleService". Press "OK" to add the service reference. Now you can call our WCF service from the Silverlight client. To test this, follow these steps: 1. Open the Page1.xaml file and add a textblock to display the string returned from the WCF method call. 2. Add an event handler for the "Loaded" event of the UserControl. Complete code from Page1.xaml is given below:
<UserControl x:Class="Silverlight_With_WCF.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300" Loaded="UserControl_Loaded"> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock x:Name="textblock1" Width="200" Height="30"></TextBlock> </Grid> </UserControl>
Now go to the code behind file (Page1.xaml.cs) and add the WCF service call as shown below:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { MyService.Service1Client client = new AccessSessionFromSilverlight.MyService.Service1Client(); client.GetSessionVariableCompleted += new EventHandler(client_GetSessionVariableCompleted); client.GetSessionVariableAsync("Name"); } void client_GetSessionVariableCompleted(object sender, AccessSessionFromSilverlight.MyService.GetSessionVariableCompletedEventArgs e) {
if (e.Result == null) textblock1.Text = "Session variable not set"; else textblock1.Text = e.Result.ToString(); }
Open the web project in Solution Explorer and set the Silverlight test page as the startup page. Now run the project. You can see that the WCF service is called from Silverlight client and the result is displayed in the browser. You can download a sample project for this tutorial.
Now, open your XAML control file and add a button control as shown below:
<Grid x:Name="LayoutRoot" Background="White"> <Button x:Name="btnSayHello" Content="Say Hello" Click="btnSayHello_Click"></Button> </Grid>
Go to the code behind file for the XAML Page and add the event handler for the button click event:
In order to use the HtmlPage class, you need to include the System.Windows.Browser
using System.Windows.Browser;
You are done. Run your Silverlight application and see. When you click on the button in the Silverlight control, you can see the popup message from the Javascript function.
// Now, make the panel a child of the popup so that // the panel will be shown within the Popup when displayed. p.Child = panel1; // Set the position. p.VerticalOffset = 25; p.HorizontalOffset = 25; // Show the popup. p.IsOpen = true; } void button1_Click(object sender, RoutedEventArgs e) { // Close the popup. p.IsOpen = false; }
Now run the application. You can see the page with a button. When you click on the button, a popup layer will appear with a text label and a button in it. When you click on the button in the popup, it will close the popup.
Display rich UI elements in tooltip Silverlights ability to support UI elements in tooltip can be used to provide great user experience. We can use almost any UI element within a Tooltip. See various examples below.
Display image within a tooltip This sample code shows how to display an image within a tooltip in Silverlight:
<TextBox Width="60" Height="20" Text="My Text"> <ToolTipService.ToolTip> <Image Source="http://www.dotnetspider.com/images/spiderlogo.jpg" ></Image> </ToolTipService.ToolTip> </TextBox>
Tooltip for entire Silverlight control You can set a tooltip for the entire Silverlight control. See the below sample code:
<UserControl x:Class="SilverlightToolTip.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <StackPanel x:Name="LayoutRoot" Background="White"> </StackPanel> <ToolTipService.ToolTip> <ToolTip Content="This is tool tip for entire control"></ToolTip> </ToolTipService.ToolTip> </UserControl>
Programmatically set Tooltip You can set or change Tooltips from the code behind file. This example shows how to set a Tooltip for a button control from the code behind file:
ToolTipService.SetToolTip(MyButton, "This is new tooltip");
If you attempt to use .WAV or .AVI files with the MediaElement control, you will get the following error: Error: Unhandled Error in Silverlight 2 Application <Application Name>Code: 3001 Category: MediaError Message: AG_E_INVALID_FILE_FORMAT In order to play an .MP3 or .WMV file, you must first include the file in your Silverlight project and then set it as an Embedded Resource. In order to make an audio file an embedded resource, right click on the file in your project and select 'properties'. Then set the 'Build Action' as 'Embedded Resource. This will make the audio file embedded in to your .XAP file when compiled. Once you make the audio file as an embedded resource, you can play the file either by defining the MediaElement within your XAML or by using the code. Here is the sample code to play an audio file:
MediaElement media = new MediaElement(); Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyNamespace.Soun d1.wav"); media.SetSource(stream); media.AutoPlay = false; media.Stop(); media.Play();
The above line retrieves the audio stream from the executing assembly. Remember that the audio file is embedded in to the assembly since we set the Build Action as 'Embedded Resource. In the above code, "MyNamespace" represents the namespace of your application. "Sound1.wav" is the name of the audio file, assuming the file is located in the root of the application. If the file is within a sub directory, you may have to include the directory name as well, separated by a period.
media.SetSource(stream);
In the above line, we are setting the source for the media player.
media.AutoPlay = false;
The above line says that the player should not play the audio until we explicitly start it to play.
media.Stop(); media.Play();
In the above code, you can see that I am doing a .Stop() before .Play(). The Stop is required only if you have to play the same MediaElement more than once.
Now, you can use the "AttachEvent" property of the browsers Document object to attach your own event handler to the "oncontextmenu" event from your xaml pages. Sample code:
System.Windows.Browser.HtmlPage.Document.AttachEvent("oncontextmenu", this.OnContextMenu);
You may attach your event handler from the constructor of your XAML page. You can even do this from the constructor of your App.xaml, in which case the event handler will be triggered from every xaml page you use in the project. And here is the code to handle the event:
private void OnContextMenu(object sender, System.Windows.Browser.HtmlEventArgs e) { MessageBox.Show("You click at " + e.OffsetX + "," + e.OffsetY);
e.PreventDefault(); }
The above code sample displays the coordinates you clicked. You may replace that code to display your own menu or popup window. The code e.PreventDefault();" prevents the events from being propagated to other child controls You can download a sample project for this tutorial.
<RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="Name" Grid.Row="0" Grid.Column="0"></TextBlock> <TextBlock Text="Address 1" Grid.Row="1" Grid.Column="0"></TextBlock> <TextBlock Text="Address 2" Grid.Row="2" Grid.Column="0"></TextBlock> <TextBlock Text="City" Grid.Row="3" Grid.Column="0"></TextBlock> <TextBlock Text="State" Grid.Row="4" Grid.Column="0"></TextBlock> <TextBlock Text="Zipcode" Grid.Row="5" Grid.Column="0"></TextBlock> <TextBox x:Name="txtName" Text="{Binding Name, Mode=TwoWay}" Grid.Row="0" Grid.Column="1"></TextBox> <TextBox x:Name="txtAddress1" Text="{Binding Address1, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"></TextBox> <TextBox x:Name="txtAddress2" Text="{Binding Address2, Mode=TwoWay}" Grid.Row="2" Grid.Column="1"></TextBox> <TextBox x:Name="txtCity" Text="{Binding City, Mode=TwoWay}" Grid.Row="3" Grid.Column="1"></TextBox> <TextBox x:Name="txtState" Text="{Binding State, Mode=TwoWay}" Grid.Row="4" Grid.Column="1"></TextBox> <TextBox x:Name="txtZipcode" Text="{Binding Zipcode, Mode=TwoWay}" Grid.Row="5" Grid.Column="1"></TextBox> <Button Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" Width="50" Content="Save" x:Name="btnSave" Click="btnSave_Click"></Button> </Grid>
The above XAML defines a grid with 7 rows and 2 columns. The controls are places in appropriate rows and columns using the Grid.Row and Grid.Column property of individual controls. When placed in a web page, our Silverlight control will look like this:
Now create a class called "Address" which has properties representing various fields we need. See the sample code for the "Address" class:
public class Address { public string Name { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string City { get; set; } public string State { get; set; } public string Zipcode { get; set; } }
Go to the code behind file of the xaml class and create an instance of the Address class as shown below:
Address address;
In the constructor of the XAML page class, initialize the Address class and bind it to the UI elements as shown below:
address = new Address(); txtName.DataContext = address; txtAddress1.DataContext = address; txtAddress2.DataContext = address; txtCity.DataContext = address; txtState.DataContext = address; txtZipcode.DataContext = address;
In the above code, we are setting the DataContext property of each UI control to our "Address" object. But how do the control know which property of the address object to be used ? This is handled in the XAML. Take a look at the "txtAddress1" control. You can see that the property "Text" is set as shown below:
Text="{Binding Address1, Mode=TwoWay}"
The above line defines that we are using data binding for the "Text" property of this control, and it will use the property "Address1" of whatever object it will be bound to. Also, it states that the Mode is "TwoWay" which means the value will be read from the object and set to the "Text" property and also when the value is changed in the textbox control, it is saved back to the data source. In our case, we are binding our Address object to the textbox control. When loaded, it will display the default value from our object in the textbox. When the value is changed by the user, the datasource object will be updated with the new value from text box. Typically, when we add a new address, the object will be initialized to empty values and the textboxes will be empty. When we edit an existing address, the object will have values populated from database and it will be displayed in the UI controls using the databinding. When values are modified by the user, the datasource object will be automatically modified.
All we have to do is, save the modified datasource object in to the database. You can download a sample project for this tutorial.
I have included only 1 property (Name) in the above code. You may extend the class to add additional properties like City, State etc. The above sample code shows it is raising the PropertyChanged event when the Name is updated for the object. This will notify the bound control about the change and the target control will update it's value accordingly. The attached sample project uses a class called 'Address' as the data source. Each property of the address object is bound to a TextBlock control in the UI using "TwoWay" binding mode. When user type any text in the UI controls, the data is updated to the address object data source. Similarly, if the address object is changed in the background, the UI is automatically updated. The UI include a "Clear" button. On the click event of this button, I am reseting the properties of the address object to empty string.
private void btnClear_Click(object sender, RoutedEventArgs e) { address.Name = string.Empty; address.Address1 = string.Empty; address.Address2 = string.Empty; address.City = string.Empty; address.State = string.Empty; address.Zipcode = string.Empty; }
Through the 2-way databinding, this will automatically clear the text in the respective UI controls. You can download a sample project for this tutorial.
This code sample shows how to use the ImageBrush to set a background image for the Silverlight canvas control.
<Canvas x:Name="SnowCanvas" Width="600" Height="480"> <Canvas.Background> <ImageBrush x:Name="backgroundImageBrush" Stretch="UniformToFill" ImageSource="Images/Background.png"> </ImageBrush> </Canvas.Background> </Canvas>
The below example shows how to Fill an ellipse area with an image control. In addition, I am using the Mouse Enter and Mouse Leave events to dynamically change the image used to fill the Ellipse shape.
<Ellipse x:Name="ellipse1" MouseEnter="ellipse1_MouseEnter" MouseLeave="ellipse1_MouseLeave" Width="100" Height="100"> <Ellipse.Fill> <ImageBrush x:Name="imageBrush1" Stretch="UniformToFill" ImageSource="Images/Flower2.png"> </ImageBrush> </Ellipse.Fill> </Ellipse>
Here is the C# code to handle the Mouse Enter and Mouse Leave events and dynamically change the image in these events:
private void ellipse1_MouseEnter(object sender, MouseEventArgs e) { ImageBrush brush = new ImageBrush(); brush.ImageSource = new BitmapImage(new Uri(@"Images/Flower1.png", UriKind.Relative)); ; ellipse1.Fill = brush; } private void ellipse1_MouseLeave(object sender, MouseEventArgs e) { ImageBrush brush = new ImageBrush(); brush.ImageSource = new BitmapImage(new Uri(@"Images/Flower2.png", UriKind.Relative)); ; ellipse1.Fill = brush; }
The current versions of Internet Explorer consider Silverlight as a kind of ActiveX control. So, in order to determine if Silverlight is installed, we can attempt to create this ActiveX control using Javascript. If it fails to create the ActiveX control, we can assume that Silverlight is not installed. For other browsers like Google Chrome, Netscape, FireFox, Safari etc, this can be determined by looking in to the Plugin array of the navigator object. The Silverlight plugin is installed with the name 'Silverlight Plug-In'. The below sample code shows how to find if Silverlight is installed on the client browser or not.
<script language="javascript"> var browser = navigator.appName; // Get browser var silverlightInstalled = false; if (browser == 'Microsoft Internet Explorer') { try { var slControl = new ActiveXObject('AgControl.AgControl'); silverlightInstalled = true; } catch (e) { // Error. Silverlight not installed. } } else { // Handle Netscape, FireFox, Google chrome etc try { if (navigator.plugins["Silverlight Plug-In"]) { silverlightInstalled = true; } } catch (e) { // Error. Silverlight not installed. } } alert(silverlightInstalled); </script>