One of the new features in Silverlight 3 is enhanced binding abilities, this includes the ElementName property. What this allows you to do is bind values from other controls. While this is new to Silverlight, the desktop environment has had this for a while so you may have seen this before. However this feature is extremely useful for many different applications. This tutorial is going to show how to use this feature in a simple way.
The demo application we are going to create is below. It is a relatively simple thing. It has a list of games at the top and details of the selected game below. We are going to bind the details information in the bottom half to the SelectedItem of the list.
The first thing we are going to do is put a little bit of XAML down for the basis of our interface. We start with defining two rows for our Grid and dropping ListBox into one of them. The second row has a barrage of TextBlock controls, along with a HyperLinkButton, an Image, and a ScrollViewer. I will give a quick review of what they are going to be used for right after the code.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="400"
Width="300" Height="400">
<UserControl.Resources>
<SolidColorBrush Opacity="0" x:Name="TransparentColor" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox
x:Name="GameList"
Grid.Row="0" Grid.ColumnSpan="2" Height="70" Width="290"
Margin="5,5,5,5"/>
<Canvas Grid.Row="1">
<Image Canvas.Top="0" Canvas.Left="0" Width="300" Height="320"
Source=""
Opacity=".15" />
<HyperlinkButton Canvas.Top="5" Canvas.Left="3" Width="290"
Content=""
NavigateUri=""
FontSize="18" FontWeight="Bold" />
<TextBlock Canvas.Top="35" Canvas.Left="5"
Text="Publisher:" FontWeight="Bold" />
<TextBlock Canvas.Top="35" Canvas.Left="75"
Text=""/>
<TextBlock Canvas.Top="55" Canvas.Left="5"
Text="Developer:" FontWeight="Bold" />
<TextBlock Canvas.Top="55" Canvas.Left="75"
Text=""/>
<TextBlock Canvas.Top="75" Canvas.Left="5"
Text="Genre:" FontWeight="Bold" />
<TextBlock Canvas.Top="75" Canvas.Left="55"
Text=""/>
<TextBlock Canvas.Top="95" Canvas.Left="5"
Text="Platforms:" FontWeight="Bold" />
<TextBlock Canvas.Top="95" Canvas.Left="75"
Text=""/>
<ScrollViewer Canvas.Top="120" Canvas.Left="5"
Width="290" MaxHeight="195"
VerticalScrollBarVisibility="Auto"
Background="{StaticResource TransparentColor}">
<TextBlock Width="265" TextWrapping="Wrap"
Text=""
HorizontalAlignment="Left"/>
</ScrollViewer>
</Canvas>
</Grid>
</UserControl>
Starting at the top, our ListBox should be pretty self explanatory - it holds the list of games. The second row is filled with a Canvas to make laying out the rest of the controls easy. An Image is the first element which fills up the whole area but it is almost completely transparent, this will act as a background. The hyperlink button shows the title of the game and will link to an external page about the game. There are then a couple details text blocks. Finally, we have a ScrollViewer which has its Background set to a resource (at the top of the XAML) to make it transparent. Inside the scroll view we add a text block to display the description. We also set a max height so the area will scroll if the description of the game is too long. That pretty much takes care of the interface.
We need to create an object to hold some basic data for a game. I created a class named Game (ohhh ahhh) and filled it with a few properties.
namespace Element_Binding
{
public class Game
{
public string Name { get; set; }
public string Publisher { get; set; }
public string Developer { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public string Platforms { get; set; }
public string Genre { get; set; }
public string Url { get; set; }
public string ImageUrl { get; set; }
public override string ToString()
{
return this.Name;
}
}
}
We also need to initialize our data which is going to be done inside of our main page xaml code behind, in my case named MainPage.xaml.cs. Inside the class I built a function called InitData which initializes the data. I call this function from the constructor after InitializeComponent is called. I also created a private variable to hold the base url for the background images. That is pretty much it. The updated code is below.
{
public partial class MainPage : UserControl
{
private string baseUrl = "http://baseurl.com/images/";
public MainPage()
{
InitializeComponent();
this.InitData();
}
private void InitData()
{
List<Game> games = new List<Game>(3);
Game game = new Game();
game.Name = "Scribblenauts";
game.Publisher = "Warner Bros. Interactive";
game.Developer = "5th Cell";
game.Genre = "Puzzle Action";
game.Platforms = "Nintendo DS";
game.Description =
"Scribblenauts goes by the concept, " +
"\"Anything you write, you can use.\" The hero Maxwell " +
"has the power to utilize items in levels called Starites " +
"which allow him to later spawn material in the real world " +
"for his needs. Ladders, tools, weapons ... goldfish, even. " +
"If you can dream it, Maxwell can conjure it, and hopefully " +
"both of you can use it to solve your puzzles.";
game.Url = "http://ds.ign.com/objects/143/14304256.html";
game.Slug = "scribblenauts";
game.ImageUrl = this.baseUrl + game.Slug + ".jpg";
games.Add(game);
game = new Game();
game.Name = "Brütal Legend";
game.Publisher = "Electronic Arts";
game.Developer = "Double Fine Productions";
game.Genre = "Adventure";
game.Platforms = "XBox 360, Playstation 3";
game.Description =
"The latest creation from gaming icon Tim Schafer and the " +
"award-winning team at Double Fine, Brütal Legend is a 3rd person " +
"Action/Adventure game starring Jack Black in the role of roadie " +
"Eddie Riggs, who sets on an epic quest to build an army of rockers "+
"with only a broad axe, a big block V8 and his faithful guitar in " +
"hand. Eddie Riggs has been drawn back through time to a mythical " +
"world dripped in Rock and Roll folklore; where great Metal " +
"titans once ruled and power chords rang from the countryside " +
"for all to hear. When an oppressed people request Eddie’s " +
"knowledge of modern warfare, he pulls from his own experience " +
"in the only occupation he’s ever had, a roadie for a Heavy Metal " +
"band. From this springs the most hellacious army man has ever seen,"+
" and thus brings this ancient world into the Age of Metal.";
game.Url = "http://xbox360.ign.com/objects/142/14210507.html";
game.Slug = "brutal-legend";
game.ImageUrl = this.baseUrl + game.Slug + ".jpg";
games.Add(game);
game = new Game();
game.Name = "Uncharted: Drake's Fortune";
game.Publisher = "Sony Computer Entertainment";
game.Developer = "Naughty Dog Software";
game.Genre = "Action Adventure";
game.Platforms = "Playstation 3";
game.Description =
"A 400-year-old clue in the coffin of Sir Francis Drake sets a " +
"modern-day fortune hunter on an exploration for the fabled " +
"treasure of El Dorado, leading to the discovery of a forgotten " +
"island in the middle of the Pacific Ocean. The search turns " +
"deadly when Nathan Drake becomes stranded on the island and " +
"hunted by mercenaries. Outnumbered and outgunned, Drake and his " +
"companions must fight to survive as they begin to unravel the " +
"terrible secrets hidden on the Island.";
game.Url = "http://ps3.ign.com/objects/812/812550.html";
game.Slug = "uncharted-drakes-fortune";
game.ImageUrl = this.baseUrl + game.Slug + ".jpg";
games.Add(game);
GameList.ItemsSource = games;
GameList.SelectedIndex = 0;
}
}
}
Ok, let's get down to it. We are here to do some binding and mostly everything up to this point has been ground work. To bind values we use the Binding markup extension. This is done by placing curly brackets, the Binding keyword, and the property to bind to. The the basic syntax is as follows, {Binding Object.Value}, where Object.Value is the object and property to bind to.
In our case, however, we are going to throw in a little wrinkle with the ElementName property. To use this guy we drop a comma at the end of binding statement, then ElementName= and the name of the element that owns the property. So this would look like {Binding Text, ElementName=MyTextBlock} if we were binding from a text block named MyTextBlock and its property Text.
Well, enough talking let's put this into action. Looking at our Image control you can see our Source property is blank. We fill that in with {Binding SelectedItem.ImageUrl, ElementName=GameList}. This is saying go to the GameList control (our list) and pull SelectedItem.ImageUrl and that is our source for the image. Now because the selected item on list is a Game object we can pull the ImageUrl. Doing the same thing for the rest of the properties of our selected game will result in an updated XAML file like below.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="400"
Width="300" Height="400">
<UserControl.Resources>
<SolidColorBrush Opacity="0" x:Name="TransparentColor" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox
x:Name="GameList"
Grid.Row="0" Grid.ColumnSpan="2" Height="70" Width="290"
Margin="5,5,5,5"/>
<Canvas Grid.Row="1">
<Image Canvas.Top="0" Canvas.Left="0" Width="300" Height="320"
Source="{Binding SelectedItem.ImageUrl, ElementName=GameList}"
Opacity=".15" />
<HyperlinkButton Canvas.Top="5" Canvas.Left="3" Width="290"
Content="{Binding SelectedItem.Name, ElementName=GameList}"
NavigateUri="{Binding SelectedItem.Url, ElementName=GameList}"
FontSize="18" FontWeight="Bold" />
<TextBlock Canvas.Top="35" Canvas.Left="5"
Text="Publisher:" FontWeight="Bold" />
<TextBlock Canvas.Top="35" Canvas.Left="75"
Text="{Binding SelectedItem.Publisher, ElementName=GameList}"/>
<TextBlock Canvas.Top="55" Canvas.Left="5"
Text="Developer:" FontWeight="Bold" />
<TextBlock Canvas.Top="55" Canvas.Left="75"
Text="{Binding SelectedItem.Developer, ElementName=GameList}"/>
<TextBlock Canvas.Top="75" Canvas.Left="5"
Text="Genre:" FontWeight="Bold" />
<TextBlock Canvas.Top="75" Canvas.Left="55"
Text="{Binding SelectedItem.Genre, ElementName=GameList}"/>
<TextBlock Canvas.Top="95" Canvas.Left="5"
Text="Platforms:" FontWeight="Bold" />
<TextBlock Canvas.Top="95" Canvas.Left="75"
Text="{Binding SelectedItem.Platforms, ElementName=GameList}"/>
<ScrollViewer Canvas.Top="120" Canvas.Left="5"
Width="290" MaxHeight="195"
VerticalScrollBarVisibility="Auto"
Background="{StaticResource TransparentColor}">
<TextBlock Width="265" TextWrapping="Wrap"
Text="{Binding SelectedItem.Description, ElementName=GameList}"
HorizontalAlignment="Left"/>
</ScrollViewer>
</Canvas>
</Grid>
</UserControl>
That pretty much wraps this tutorial up. Using binding properties are not hard once you have the basic concepts down. The ElementName property is one you should definitely know about especially now that it's available in Silverlight. As always if you have any questions feel free to leave a comment or post something in the forums.
07/15/2009 - 12:13
It's about time this was added. Every time I went to write a Silverlight app I'd attempt to use this before I remembered it's not supported.
07/15/2009 - 12:50
Yeah I agree, it's really something you just assume is there and you are able to use it. You don't realize how useful it is until it's gone.
07/15/2009 - 21:01
So, what kind of apps are you doing with SL? Internet, intranet? Regular, boring, biz or more like flashy (pun intended :) apps? Something for your own fun or actually real work?
07/16/2009 - 08:36
Nothing official. Usually just a simple app for a tutorial or something little just for fun. I work with WPF every day, so it's always a challenge remembering/figuring out what's not in Silverlight.
07/27/2009 - 00:19
I agree with this. You don't realize how useful it is until it's gone. Thanks for this post.
06/09/2011 - 14:59
In my blog I described the BoundToSelfControl, which binds itself to itself and in the same time it saves what was passed through DataContext in special field. Take a look at http://dotnetfollower.com/wordpress/2011/06/silverlight-for-windows-phone-7-how-to-bound-usercontrol-to-itself/
Thanks!
.NET Follower (http://dotnetfollower.com)
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.