{"id":238,"date":"2007-03-16T00:00:00","date_gmt":"2007-03-16T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/getting-started-with-xaml\/"},"modified":"2021-05-17T18:36:49","modified_gmt":"2021-05-17T18:36:49","slug":"getting-started-with-xaml","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/getting-started-with-xaml\/","title":{"rendered":"Getting Started with XAML"},"content":{"rendered":"<h2>Creating .NET 3 Applications with XAML<\/h2>\n<p>Microsoft&#8217;s .NET 3 introduces the option of using markup to create Windows applications, much as we&#8217;ve used HTML and related markup to create web applications for the past decade. This is a major break-through and a distinct step on the path towards merging the development process of creating web and desktop applications.<\/p>\n<p>This new markup language is called eXtensible Application Markup Language, or XAML (pronounced \/&#8217;z\u00c3\u00a6m\u00c9l\/ to rhyme with camel). Every XAML object represents a CLR object, and every CLR object may be created declaratively in XAML.<\/p>\n<p>In this article we&#8217;ll create a meaningful, working XAML application. We&#8217;ll take you through the creation process, with the goal of demonstrating the flexibility of the language and acquainting you with the fundamentals of creating a working Windows application declaratively.<\/p>\n<h3>Getting Started With XAML<\/h3>\n<p>Every Window is declared as a panel and every property is declared as an element, or an attribute of an element. In its simplest form, this looks very similar to HTML:<\/p>\n<pre>&lt;Button Width=\"20\" Height=\"10\"&gt;OK Button&lt;\/Button&gt;\r\n<\/pre>\n<p>In fact, XAML is an XML-based superset of HTML, combining the power of HTML to define content, with that of CSS to define layout (carefully separating the two, to the relief of experienced CSS programmers).<\/p>\n<div>\n<em>Note: To follow along with the examples in this article, you will need to install the release version of .NET 3, which will run happily and harmlessly side-by-side with .NET 2 on any computer running Vista, Windows XP (SP2), or Windows Server 2003 SP1. <\/em>\n<\/div>\n<h3>Core XAML Elements<\/h3>\n<p>While we won&#8217;t even try to cover everything in XAML in this article, we will cover some core elements, both to give you a feel for how XAML applications work and to lay the ground work for walking you through a robust sample application.<\/p>\n<p>A panel element is a container. Panels come in several different shapes and sizes. Depending on their features they are useful for containing other elements.<\/p>\n<p>Root elements are special derivations of panel elements and serve as the fundamental container for the page. Each page will have exactly one root element.<\/p>\n<p>Control elements are user-manipulated objects that help with data or user interactions.<\/p>\n<h3>The PelotonShack Project<\/h3>\n<p>With these elements, we are going to build a data-bound page that will offer a catalog of bicycle parts from the AdventureWorks2000 database. On the left, there will be a scrolling display of images taken from the database. As the user scrolls over each image, it (that is, the image, not the user) will grow slightly and come into focus. If the user clicks on the image, it will be highlighted in the larger area on the right and its details will be displayed in text, as shown in Figure 1.<\/p>\n<p>\u00a0<img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig1_XAML.gif\" alt=\"363-Fig1_XAML.gif\" \/><br \/>\n<em>Figure 1: in which the selected image (not the user) is shown in detail in the right hand panel<\/em><\/p>\n<h3>Creating the Web Application<\/h3>\n<p>To create this application, begin by opening Visual Studio and creating a new <span class=\"CodeInText\">Project<\/span>. Choose the Windows Application (WPF) template, set your directory and set the solution name to <span class=\"CodeInText\">PelotonShack<\/span>, as shown in Figure 2.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig2_XAML.gif\" alt=\"363-Fig2_XAML.gif\" \/><br \/>\n<em>Figure 2: creating the web application<\/em><\/p>\n<p>Windows will create a development environment and establish your first window, which it will also name for you:<\/p>\n<pre>&lt;Window x:Class=\"PelotonShack.Window1\"\u00a0\u00a0\u00a0 xmlns=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation\"\u00a0\u00a0\u00a0 xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\"\u00a0\u00a0\u00a0 Title=\"PelotonShack\" Height=\"300\" Width=\"300\"&gt;\u00a0\u00a0\u00a0 &lt;Grid&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ...\u00a0\u00a0\u00a0 &lt;\/Grid&gt;&lt;\/Window&gt;<\/pre>\n<p>While there will certainly come a time (and soon) when Visual Studio will offer a complete and working toolkit for building WPF applications, for now we&#8217;re going to have the most success and least frustration if we write directly in XAML, in the lower markup window.<\/p>\n<p>Start by setting the height of Window1 to 600 and the width to 900 (you can fine-tune these numbers later).<\/p>\n<p>Within the <span class=\"CodeInText\">Grid<\/span>, we&#8217;ll want to add <span class=\"CodeInText\">Grid.Resources<\/span> (to manage styles, <span class=\"CodeInText\">GradientBrushes<\/span>, etc.) and we&#8217;ll want to add column definitions.<\/p>\n<h4>The Header<\/h4>\n<p>An easy place to start is by adding the header, as shown in Figure 3:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig3_XAML.gif\" alt=\"363-Fig3_XAML.gif\" \/><\/p>\n<p><em>Figure 3: adding the header<\/em><\/p>\n<p>To create this, we&#8217;ll use a text block and style it. The text block is pretty straightforward:<\/p>\n<pre>&lt;TextBlock Style=\"{DynamicResource TitleText}\"&gt;\u00a0\u00a0 &lt;Span&gt;The Peloton Shack: &lt;\/Span&gt;\u00a0\u00a0 &lt;Span FontStyle=\"Italic\"&gt; keeping you in the pack!&lt;\/Span&gt;&lt;\/TextBlock&gt;<\/pre>\n<p>Notice, however, that the <span class=\"CodeInText\">TextBlock<\/span> element is marked with a style reference to the <span class=\"CodeInText\">DynamicResource<\/span> &#8216;<span class=\"CodeInText\">TitleText<\/span>&#8216;. Resources are separated out in their own section, so the complete XAML at this point looks as shown in example 1:<\/p>\n<pre>                          Example 1&lt;Window x:Class=\"PelotonShack.Window1\"\u00a0\u00a0\u00a0 xmlns=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation\"\u00a0\u00a0\u00a0 xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\"\u00a0\u00a0\u00a0 Title=\"PelotonShack\" Height=\"600\" Width=\"900\"&gt;\u00a0\u00a0\u00a0 &lt;Grid&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Grid.Resources&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Style x:Key=\"TitleText\" TargetType=\"{x:Type TextBlock}\" &gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Setter Property=\"FontFamily\" Value=\"Segoe Black\" \/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Setter Property=\"FontSize\" Value=\"24px\" \/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Setter Property=\"Foreground\" Value=\"MidnightBlue\" \/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/Style&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/Grid.Resources&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;TextBlock Style=\"{DynamicResource TitleText}\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Span&gt;The Peloton Shack: &lt;\/Span&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Span FontStyle=\"Italic\"&gt; keeping you in the pack!&lt;\/Span&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/TextBlock&gt;\u00a0\u00a0\u00a0 &lt;\/Grid&gt;&lt;\/Window&gt;\u00a0<\/pre>\n<p>From such humble beginnings, all the rest will follow in just a few easy steps.<\/p>\n<h4>\u00a0Adding the List Box<\/h4>\n<p>To add the list box of products, we need to accomplish a few tasks all at the same time.<\/p>\n<p>1. Add a panel to hold the list box in a specific place in our window.<\/p>\n<p>2. Add a list box to hold the images.<\/p>\n<p>3. Include style information to tell the list box how to render the data (as images).<\/p>\n<p>4. Bind the list box to a query of the images from the database.<\/p>\n<p>The panel we&#8217;ll use to hold the list box will, ultimately, have the list box on the left, the larger image on the right and text below. That is, it needs to have two columns and a row. A stack panel can hold items one above the other or one next to another, but when you need to have both rows and columns, the panel you need is a grid:<\/p>\n<pre>&lt;Grid x:Name=\"MainGrid\" Margin=\"125,99,127,118\" Width=\"Auto\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Height=\"Auto\" RenderTransformOrigin=\"0.5,0.5\"&gt;\u00a0\u00a0\u00a0 &lt;Grid.ColumnDefinitions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;ColumnDefinition Width=\"0.33*\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;ColumnDefinition Width=\"0.66*\"\/&gt;\u00a0\u00a0\u00a0 &lt;\/Grid.ColumnDefinitions&gt;\u00a0\u00a0\u00a0 &lt;Grid.RowDefinitions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;RowDefinition\/&gt;\u00a0\u00a0\u00a0 &lt;\/Grid.RowDefinitions&gt;\u00a0\u00a0\u00a0 &lt;ContentControl x:Name=\"MasterPane\" HorizontalAlignment=\"Center\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 VerticalAlignment=\"Stretch\" RenderTransformOrigin=\"0.5,0.5\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;ListBox x:Name=\"MasterList\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Width=\"Auto\" Height=\"Auto\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 RenderTransformOrigin=\"0.5,0.5\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ItemsSource=\"{Binding Mode=Default}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ItemTemplate=\"{DynamicResource ProductDataTemplate}\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ItemContainerStyle=\"{DynamicResource ProductTemplateItemStyle}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HorizontalAlignment=\"Center\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SelectedIndex=\"0\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IsSynchronizedWithCurrentItem=\"True\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ScrollViewer.VerticalScrollBarVisibility=\"Visible\"\u00a0\u00a0\u00a0\u00a0&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/ListBox&gt;\u00a0\u00a0\u00a0 &lt;\/ContentControl&gt;\u00a0\u00a0\u00a0 &lt;ContentControl\u00a0 x:Name=\"DetailsPane\" Grid.Column=\"1\" \/&gt;\u00a0&lt;\/Grid&gt;<\/pre>\n<p>The first two lines set up the grid&#8217;s attributes (margin, width, etc.). This is followed by the <span class=\"CodeInText\">Grid<\/span> column definitions, in which we define two columns: one will occupy 1\/3 of the grid&#8217;s width, while the second will occupy the remaining 2\/3 of the grid&#8217;s width. One row is defined in the <span class=\"CodeInText\">Row<\/span> definitions.<\/p>\n<p>Following the <span class=\"CodeInText\">Row<\/span> and <span class=\"CodeInText\">Column<\/span> definitions are two content controls: <span class=\"CodeInText\">MasterPane<\/span> and <span class=\"CodeInText\">DetailsPane<\/span>. The second content control, <span class=\"CodeInText\">DetailsPane<\/span>, is left empty for now. The first content control holds the list box. The key attribute for the list box is that the <span class=\"CodeInText\">ItemSource<\/span> is set to bind using the default mode. Since this is placed within a window where the <span class=\"CodeInText\">DataContext<\/span> was set to &#8216;<span class=\"CodeInText\">theTable<\/span>&#8216;, the list box will use &#8216;<span class=\"CodeInText\">theTable<\/span>&#8216; as its binding context. The style for binding is set by the <span class=\"CodeInText\">ItemTemplate<\/span>.<\/p>\n<pre>ItemsSource=\"{Binding Mode=Default}\" ItemTemplate=\"{DynamicResource ProductDataTemplate}\"The ProductDataTemplate must be defined up in the Grid.Resources section. &lt;DataTemplate x:Key=\"ProductDataTemplate\"&gt;\u00a0\u00a0 &lt;StackPanel HorizontalAlignment=\"Center\" \u00a0\u00a0\u00a0\u00a0\u00a0 Background=\"{DynamicResource ListBoxGradient}\"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 Height=\"Auto\" Width=\"150\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Image Source=\"{Binding Path=ThumbNailPhotoFilePath}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ContextMenuService.IsEnabled=\"True\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ContextMenuService.ContextMenu=\"{Binding Path=Name}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HorizontalAlignment=\"Center\" \/&gt;\u00a0\u00a0 &lt;\/StackPanel&gt;&lt;\/DataTemplate&gt;<\/pre>\n<p>It consists of a stack panel whose horizontal alignment is set to center the items and whose image will be retrieved from the binding where the path is set to <em>ThumbNailPhotoFilePath . <\/em>This is a column that will be retrieved for every row as a result of the select statement that will generate the <span class=\"CodeInText\">DataTable<\/span> we&#8217;ll be using as the <span class=\"CodeInText\">DataContext<\/span> for this list box.<\/p>\n<p>All of the work for generating the <span class=\"CodeInText\">DataTable<\/span>, and associating it with the context, is accomplished in the code-behind file, the constructor for the Window class:<\/p>\n<pre>public partial class Window1 : System.Windows.Window{\u00a0\u00a0 DataTable theTable = new DataTable();\u00a0\u00a0 public Window1()\u00a0\u00a0 {\u00a0\u00a0\u00a0\u00a0\u00a0 InitializeComponent();\u00a0\u00a0\u00a0\u00a0\u00a0 String connString = @\"Data Source=&lt;Your Server&gt;;Initial \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Catalog=AdventureWorks2000;Integrated Security=True\";\u00a0\u00a0\u00a0\u00a0\u00a0 String query = @\"SELECT\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.ProductID, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.Name, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.ProductNumber, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.ListPrice, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.Color, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.Size, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.Style, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ProductPhoto.ThumbNailPhotoFilePath, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ProductPhoto.LargePhotoFilePath\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FROM\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 INNER JOIN\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ProductPhoto \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ON \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Product.ProductPhotoID = ProductPhoto.ProductPhotoID \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 WHERE\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (Product.ProductPhotoID = ProductPhoto.ProductPhotoID \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AND Product.ListPrice &lt; 100)\";\u00a0\u00a0\u00a0\u00a0\u00a0 using ( SqlConnection conn = new SqlConnection( connString ) )\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SqlDataAdapter da = new SqlDataAdapter( query, conn );\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 da.Fill( theTable );\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\u00a0\u00a0\u00a0\u00a0 DataContext = theTable;\u00a0\u00a0 }\u00a0<\/pre>\n<p>The net result is a scrollable list of images extracted from the database, as demonstrated in Figure 4:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig4_XAML.gif\" alt=\"363-Fig4_XAML.gif\" \/><\/p>\n<p><em>Figure 4: a scrollable list of images<\/em><\/p>\n<h4>Adding Events<\/h4>\n<p>We&#8217;d like to be able to mouse over the list and make the image currently highlighted by the mouse stand out more than the others. We&#8217;ll do this by reducing the opacity of the images to 60% and then increasing that to 100% when the mouse hovers over the image. To accomplish this effect, we add animation, using a story board.<\/p>\n<p>We&#8217;ll indicate that the starting opacity is .60 (60%); and we&#8217;ll designate that over the course of two tenths of a second that opacity should increase to 100% when the event <span class=\"CodeInText\">MouseEnter<\/span> is registered. This opacity will also return to 60% when the <span class=\"CodeInText\">MouseLeave<\/span> event is raised. We declare these requirements by creating a <span class=\"CodeInText\">ProductTemplateItemStyle<\/span> for the <span class=\"CodeInText\">ItemContainer<\/span> and then creating that style within the <span class=\"CodeInText\">Resources<\/span> section:<\/p>\n<pre>&lt;Style x:Key=\"ProductTemplateItemStyle\" TargetType=\"{x:Type ListBoxItem}\"&gt;\u00a0\u00a0 &lt;Setter Property=\"Opacity\" Value=\".60\" \/&gt;\u00a0\u00a0 &lt;Style.Triggers&gt;\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;EventTrigger RoutedEvent=\"Mouse.MouseEnter\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;EventTrigger.Actions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;BeginStoryboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Storyboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;DoubleAnimation \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Duration=\"0:0:0.2\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Storyboard.TargetProperty=\"Opacity\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 To=\"1.0\" \/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/Storyboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/BeginStoryboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/EventTrigger.Actions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/EventTrigger&gt;\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;EventTrigger RoutedEvent=\"Mouse.MouseLeave\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;EventTrigger.Actions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;BeginStoryboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;Storyboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;DoubleAnimation \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Duration=\"0:0:0.2\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Storyboard.TargetProperty=\"Opacity\" \/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/Storyboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/BeginStoryboard&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/EventTrigger.Actions&gt;\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/EventTrigger&gt;\u00a0\u00a0 &lt;\/Style.Triggers&gt;&lt;\/Style&gt;<\/pre>\n<p>The effect is powerful: As you mouse over each item, it appears to light up.<\/p>\n<h3>Creating the Detail View<\/h3>\n<p>We can now add the second container control to hold the larger image of the selected item and its description. The most interesting thing we&#8217;ll do here is add a &#8216;reflection&#8217;:<\/p>\n<pre>&lt;ContentControl x:Name=\"DetailsPane\" Grid.Column=\"1\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Margin=\"15,0,0,0\" Width=\"Auto\" Height=\"Auto\" \u00a0\u00a0 RenderTransformOrigin=\"0.5,0.5\"&gt;\u00a0&lt;Grid x:Name=\"DetailsGrid\" Width=\"Auto\" Height=\"Auto\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 RenderTransformOrigin=\"0.5,0.5\"&gt;\u00a0\u00a0&lt;Grid.ColumnDefinitions&gt;\u00a0\u00a0\u00a0&lt;ColumnDefinition\/&gt;\u00a0\u00a0&lt;\/Grid.ColumnDefinitions&gt;\u00a0\u00a0&lt;Grid.RowDefinitions&gt;\u00a0\u00a0\u00a0&lt;RowDefinition\/&gt;\u00a0\u00a0&lt;\/Grid.RowDefinitions&gt;\u00a0\u00a0&lt;StackPanel&gt;\u00a0\u00a0\u00a0&lt;Image x:Name=\"ProductImage\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 RenderTransformOrigin=\"0.5,0.5\"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Width=\"Auto\" Height=\"200\" Source=\"{Binding Path=LargePhotoFilePath}\"\/&gt;\u00a0\u00a0\u00a0&lt;Rectangle\u00a0 Fill=\"{DynamicResource ReflectionBrush}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Margin=\"0,0,0,0\" Stroke=\"{x:Null}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Width=\"{Binding Path=ActualWidth, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ElementName=ProductImage, Mode=Default}\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Height=\"200\" RenderTransformOrigin=\"0.5,0.5\"&gt;\u00a0\u00a0\u00a0\u00a0&lt;Rectangle.LayoutTransform&gt;\u00a0\u00a0\u00a0\u00a0\u00a0&lt;TransformGroup&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;ScaleTransform ScaleX=\"1\" ScaleY=\"-1\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;SkewTransform AngleX=\"0\" AngleY=\"0\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;RotateTransform Angle=\"0\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;TranslateTransform X=\"0\" Y=\"0\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/TransformGroup&gt;\u00a0\u00a0\u00a0\u00a0&lt;\/Rectangle.LayoutTransform&gt;\u00a0\u00a0\u00a0\u00a0&lt;Rectangle.OpacityMask&gt;\u00a0\u00a0\u00a0\u00a0\u00a0&lt;LinearGradientBrush StartPoint=\"0.5,1.5\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 EndPoint=\"0.5,-0.5\"&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;GradientStop Color=\"#7FFFFFFF\" Offset=\"0.21\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;GradientStop Color=\"#00FFFFFF\" Offset=\"0.392\"\/&gt;\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/LinearGradientBrush&gt;\u00a0\u00a0\u00a0\u00a0&lt;\/Rectangle.OpacityMask&gt;\u00a0\u00a0\u00a0&lt;\/Rectangle&gt;\u00a0\u00a0&lt;\/StackPanel&gt;\u00a0&lt;TextBlock x:Name=\"Name\" Margin=\"0,0,2,19\" HorizontalAlignment=\"Left\" \u00a0\u00a0\u00a0 VerticalAlignment=\"Bottom\" Width=\"64\" Height=\"26\" \u00a0\u00a0\u00a0\u00a0\u00a0 RenderTransformOrigin=\"0.5,0.5\" TextWrapping=\"Wrap\" \u00a0\u00a0\u00a0\u00a0\u00a0 Text=\"{Binding Path=Name}\" TextAlignment=\"Left\"\/&gt;\u00a0&lt;TextBlock x:Name=\"ProductNumber\" Margin=\"0,0,2,19\" \u00a0\u00a0\u00a0 HorizontalAlignment=\"Center\" VerticalAlignment=\"Bottom\" \u00a0\u00a0\u00a0\u00a0\u00a0 Width=\"64\" Height=\"26\" RenderTransformOrigin=\"0.5,0.5\" \u00a0\u00a0\u00a0\u00a0\u00a0 TextAlignment=\"Center\"\u00a0 Text=\"{Binding Path=ProductNumber}\"\/&gt;\u00a0&lt;TextBlock x:Name=\"ListPrice\" Margin=\"0,0,2,19\" \u00a0\u00a0\u00a0 HorizontalAlignment=\"Right\" VerticalAlignment=\"Bottom\" Width=\"64\" \u00a0\u00a0\u00a0\u00a0\u00a0 Height=\"26\" RenderTransformOrigin=\"0.5,0.5\" \u00a0\u00a0\u00a0\u00a0\u00a0 TextAlignment=\"Right\" Text=\"{Binding Path=ListPrice, \u00a0\u00a0\u00a0\u00a0\u00a0 Converter={StaticResource myNumberFormatter}, \u00a0\u00a0\u00a0\u00a0\u00a0 ConverterParameter='$#,###.00'}\"\/&gt;\u00a0&lt;\/Grid&gt;&lt;\/ContentControl&gt;<\/pre>\n<h3>Creating the Reflection<\/h3>\n<p>The reflection is created by adding a grid within the content control. Within that grid we will add a stack panel. The image is stacked on top of a rectangle that uses a <span class=\"CodeInText\">LayoutTransform<\/span> to flip the image upside down (ScaleY = -1). The rectangle then uses an <span class=\"CodeInText\">OpacityMask<\/span> with a <span class=\"CodeInText\">LinearGradientBrush<\/span> that starts out at 0.5,1.5 and ends at 0.5, -0.5; that is, the image appears to fade away quickly:<\/p>\n<pre>&lt;Rectangle.LayoutTransform&gt;\u00a0       &lt;TransformGroup&gt;\u00a0\u00a0              &lt;ScaleTransform ScaleX=\"1\" ScaleY=\"-1\"\/&gt;\u00a0\u00a0              &lt;SkewTransform AngleX=\"0\" AngleY=\"0\"\/&gt;\u00a0\u00a0              &lt;RotateTransform Angle=\"0\"\/&gt;\u00a0\u00a0              &lt;TranslateTransform X=\"0\" Y=\"0\"\/&gt;\u00a0        &lt;\/TransformGroup&gt;&lt;\/Rectangle.LayoutTransform&gt;&lt;Rectangle.OpacityMask&gt;\u00a0       &lt;LinearGradientBrush StartPoint=\"0.5,1.5\" EndPoint=\"0.5,-0.5\"&gt;\u00a0\u00a0            &lt;GradientStop Color=\"#7FFFFFFF\" Offset=\"0.21\"\/&gt;\u00a0\u00a0            &lt;GradientStop Color=\"#00FFFFFF\" Offset=\"0.392\"\/&gt;\u00a0       &lt;\/LinearGradientBrush&gt;&lt;\/Rectangle.OpacityMask&gt;<\/pre>\n<p>The effect can be seen in this close-up of the rendered image in Figure 5:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig5_XAML.gif\" alt=\"363-Fig5_XAML.gif\" \/><\/p>\n<p><em>Figure 5: reflection<\/em><\/p>\n<p>To finish up, we&#8217;ll add a <span class=\"CodeInText\">GridSplitter<\/span>, telling it which column we want to split. This will allow the user to reallocate the relative space between the list box and the details:<\/p>\n<pre>&lt;GridSplitter x:Name=\"GridSplitter1\" \u00a0\u00a0\u00a0\u00a0\u00a0 Grid.Column=\"1\" Margin=\"1.5,1.5,0,3\" \u00a0\u00a0 HorizontalAlignment=\"Left\" Width=\"11.5\" \u00a0\u00a0 Height=\"Auto\" RenderTransformOrigin=\"0.5,0.5\"\/&gt;<\/pre>\n<p>The effect is shown in Figure 6:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/363-Fig6_XAML.gif\" alt=\"363-Fig6_XAML.gif\" \/><\/p>\n<p><em>Figure 6: the gridsplitter<\/em><\/p>\n<h3>Complete Source<\/h3>\n<p>The complete source can be downloaded\u00a0with this article.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>See for yourself the flexibility of XAML, as Jesse Liberty and Alex Horovitz show you how to create an interactive Windows application declaratively, in .NET 3.0.&hellip;<\/p>\n","protected":false},"author":221820,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4717,4229,4178,4716,4715,4714],"coauthors":[49721],"class_list":["post-238","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-3","tag-net-framework","tag-bi","tag-reflection","tag-windows-application","tag-xaml"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/238","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221820"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=238"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/238\/revisions"}],"predecessor-version":[{"id":75068,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/238\/revisions\/75068"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=238"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}