CHAPTER 14 SILVERLIGHT INTRODUCTION 355 9. Add an event handler for the click of the Media button in MediaTest_Loaded: this.cmdMediaTest.Click += new RoutedEventHandler(cmdMediaTest_Click); 10. Add the event handler code: void cmdMediaTest_Click(object sender, RoutedEventArgs e) { PageNavigator.LoadPage(new Media.MediaPlayerTest()); } 11. Press F5 to run your application and click the Media button. You should see the WMV file playing. You can click the buttons to pause/play and stop the media player. Silverlight contains rich media functionality allowing you to jump to specific points on the video, alter playback speed, and so on. TIP You can even use media files as a brush to fill in XAML elements. Additional Controls In addition to the standard Silverlight controls such as TextBox, Image, and ComboBox additional controls such as a DataGrid, Slider, and Calendar are available. The easiest way to use controls such as DataGrid is to drag them from the toolbar and have VS sort out the references for you. Data Binding There are few applications that do not have to work with data. Silverlight offers a rich binding model that makes it very easy to work with data. Let’s create a simple example to bind data to a text box: 1. Add a new folder called DataBinding to the example project. 2. Right-click and Add➤New Item➤Silverlight UserControl. Call it DataBindingTest. 3. In the XAML, you need to add a namespace reference to the assemblies you're going to use. Add the following line in the UserControl tag of DataBindingTest.xaml: xmlns:Data="clr- namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 4. Between the layout root tag add the following: <StackPanel Orientation="Vertical"> <TextBlock>Bound programmatically:</TextBlock> <TextBox x:Name="txtBoundProgrammatically" Width="300" Height="20"></TextBox> <TextBlock>Bound declaratively:</TextBlock> <TextBox x:Name="txtDeclaration" Width="300" Text="{Binding Title, Mode=OneWay}" Height="20" ></TextBox> </StackPanel> CHAPTER 14 SILVERLIGHT INTRODUCTION 356 5. Open ~/DataBinding/DataBindingTest.xaml.cs and add the following using directive: using System.Windows.Data; 6. You need something to bind the controls to. You will create a class called Movie that will have two properties: Title and Length. Add the Movie class to the DataBindingTest.xaml.cs code: public class Movie : System.ComponentModel.INotifyPropertyChanged { // implement the required event for the interface public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; private string _title; private string _length; public string Title { get { return _title; } set { _title = value; //Tell Silverlight Title property has changed NotifyChanged("Title"); } } public string Length { get { return _length; } set { _length = value; //Tell Silverlight Length property has changed NotifyChanged("Length"); } } CHAPTER 14 SILVERLIGHT INTRODUCTION 357 //This procedure raises the event property changed //so Silverlight knows when a value has changed public void NotifyChanged(string PropertyName) { if (PropertyChanged != null) { PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(PropertyName)); } } } 7. Change the DataBindingTest class code to the following: public partial class DataBindingTest : UserControl { public List<Movie> MoviesList = new List<Movie>(); public DataBindingTest() { InitializeComponent(); this.Loaded += new RoutedEventHandler(DataBindingTest_Loaded); } void DataBindingTest_Loaded(object sender, RoutedEventArgs e) { //Create items for binding PopulateItems(); //Create binding programmatically CreateBinding_programmatically(); //Set binding declaratively txtDeclaration.DataContext = MoviesList [0]; } public void PopulateItems() { //Create a list of items Movie Movie1 = new Movie(); Movie Movie2 = new Movie(); Movie Movie3 = new Movie(); Movie1.Title = "Terminator"; Movie1.Length = "120"; Movie2.Title = "Conan the barbarian"; Movie2.Length = "124"; Movie3.Title = "Robocop"; Movie3.Length = "130"; CHAPTER 14 SILVERLIGHT INTRODUCTION 358 MoviesList.Add(Movie1); MoviesList.Add(Movie2); MoviesList.Add(Movie3); } public void CreateBinding_programmatically() { //Creates a binding programmatically Binding NewBinding = new Binding("Now"); NewBinding.Source = System.DateTime.Now; NewBinding.Mode = BindingMode.OneWay; txtBoundProgrammatically.SetBinding(TextBox.TextProperty, NewBinding); } } 8. All you now need to do is link MainMenu to the data binding test page. Open ~/MainMenu.xaml.cs. 9. Add the following code to the MainMenu_Loaded() method in MainMenu.xaml.cs: this.cmdDataBind.Click += new RoutedEventHandler(cmdDataBind_Click); 10. Add a method to the click event of the data bind button: void cmdDataBind_Click(object sender, RoutedEventArgs e) { PageNavigator.LoadPage(new DataBinding.DataBindingTest()); } 11. Press F5 to run the application. You should see two text boxes: the first displays the current time and date, and the other displays “The Terminator” (item 0 in MoviesList). So what have you done here? First, you created a binding programmatically: //Creates a binding programmatically public void CreateBinding_programmatically() { //Creates a binding programmatically Binding NewBinding = new Binding("Now"); NewBinding.Source = System.DateTime.Now; NewBinding.Mode = BindingMode.OneWay; txtBoundProgrammatically.SetBinding(TextBox.TextProperty, NewBinding); } You then set the source (value) to today’s date and then linked the binding to the txtBoundProgrammatically text box. To bind the TextBox txtDeclaration declaratively, first set the data context with the following code: txtDeclaration.DataContext = MoviesList[0]; Set the Text property of the text box as follows: <TextBox x:Name="txtDeclaration" Width="300" Text="{Binding Title, Mode=OneWay}" Height="20" ></TextBox> CHAPTER 14 SILVERLIGHT INTRODUCTION 359 DataBinding Modes In the preceding example, you bound a TextBox to the Title property of Movie and defined the binding mode as one way: <TextBox x:Name="txtDeclaration" Width="300" Text="{Binding Title, Mode=OneWay}" Height="20" ></TextBox> Silverlight offers three binding modes: • OneTime: This is the lightweight option and should be used if the value will never change from what it is initialized as. • OneWay: If the item the object is bound to is changed, the bound property will be updated as well. If you change the bound property, it will not affect the object it is bound to. • TwoWay: Like OneWay binding, but any changes to the bound property will also alter the bound object. Data Binding and Dependency Properties As mentioned earlier, data binding uses dependency properties to maintain the relationship between the object and datasource. If you change an item that is databound then any other controls bound to the data item will change as well. Let’s create an example to demonstrate this. 1. Open ~/DataBinding/DataBindingTest.xaml. 2. Add the following XAML after the TextBox that has the x:name set to txtDeclaration: <TextBlock>Change an object in list:</TextBlock> <Button x:Name="cmdChangeTitle" Width="100" Height="20" Content="Change Title"></Button> 3. Open DataBindingTest.xaml.cs and add a click event handler: this.cmdChangeTitle.Click+=new RoutedEventHandler(cmdChangeTitle_Click); 4. Add a method to handle the click: void cmdChangeTitle_Click(object sender, RoutedEventArgs e) { //Change an item in the list MoviesList[0].Title = "Title Changed"; } 5. Press F5 to run the application. Click the button to change the movie title. The text box that was bound to this item will then change. Note that the contents of the text box that is bound was automatically updated when you changed the class it was bound to. . Width=" 300 " Height=" 20& quot;></TextBox> <TextBlock>Bound declaratively:</TextBlock> <TextBox x:Name="txtDeclaration" Width=" 300 " Text="{Binding. "1 20& quot;; Movie2.Title = "Conan the barbarian"; Movie2.Length = "1 24& quot;; Movie3.Title = "Robocop"; Movie3.Length = "1 30& quot;; CHAPTER 14 . MoviesList [0] ; Set the Text property of the text box as follows: <TextBox x:Name="txtDeclaration" Width=" 300 " Text="{Binding Title, Mode=OneWay}" Height=" 20& quot;