Silverlight Coverflow with Reflection

This post describes how to create an attractive and compelling cover flow control using Silverlight as illustrated below.

Silverlight Coverflow with Reflection

The basis of this sample is the excellent work done by Darick C with his Silverlight Cover Flow project published on CodePlex.  To begin, download Darick’s Cover Flow contribution.  Create a new Silverlight application called “CoverFlowWithReflection” in Microsoft Visual Studio 2008, and add reference to either the Coverflow project or binary.

Below is the XAML for MainPage.xaml.  Each cover flow item is defined with an image and a textbox.

<UserControl
x:Class="CoverFlowWithReflection.MainPage"
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="640"
d:DesignHeight="480"
xmlns:c="clr-namespace:ControlLibrary;assembly=ControlLibrary"
>
<
Grid>
<
c:CoverFlowControl x:Name="CoverFlow" Margin="0,10,0,0">
<
c:CoverFlowControl.ItemTemplate>
<
DataTemplate>
<
Grid>
<
Image Source="{Binding Path=Picture, Mode=OneWay}"
Height="300"
Stretch="UniformToFill"
/>
<
TextBlock Text="{Binding Path=Name, Mode=OneWay}"
Foreground="White"
HorizontalAlignment="Center"
FontSize="12"
/>
</
Grid>
</
DataTemplate>
</
c:CoverFlowControl.ItemTemplate>
</
c:CoverFlowControl>
</
Grid>
</
UserControl>


The following snippet is for the MainPage.xaml code-behind (or MainPage.xaml.cs).  The code defines a new generic collection and assigns it to the coverflow control.  Please excuse the crazy formatting, this is required to squeeze the text into the blog.



using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace CoverFlowWithReflection {
public partial class MainPage : UserControl {
private const string PREFIX =
"http://upload.wikimedia.org/wikipedia/commons/thumb/";
private ObservableCollection<Thumbnail> _thumbnails =
new ObservableCollection<Thumbnail>();
//
// CONSTRUCTOR
//
public MainPage() {
InitializeComponent();

// Populate thumbnail collection
this._thumbnails.Add(
new Thumbnail {
Name = "Albert Einstein",
Picture = PREFIX +
"7/78/Einstein1921_by_F_Schmutzer_4.jpg" +
"/225px-Einstein1921_by_F_Schmutzer_4.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Isaac Newton",
Picture = PREFIX +
"3/39/GodfreyKneller-IsaacNewton-1689.jpg" +
"/225px-GodfreyKneller-IsaacNewton-1689.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Gottfried Leibniz",
Picture = PREFIX +
"6/6a/Gottfried_Wilhelm_von_Leibniz.jpg" +
"/200px-Gottfried_Wilhelm_von_Leibniz.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Niels Bohr",
Picture = PREFIX +
"6/6d/Niels_Bohr.jpg" +
"/180px-Niels_Bohr.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Ernest Rutherford",
Picture = PREFIX +
"5/57/Ernest_Rutherford2.jpg" +
"/200px-Ernest_Rutherford2.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Stephen Hawking",
Picture = PREFIX +
"e/eb/Stephen_Hawking.StarChild.jpg" +
"/200px-Stephen_Hawking.StarChild.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Galileo Galilei",
Picture = PREFIX +
"c/cc/Galileo.arp.300pix.jpg" +
"/225px-Galileo.arp.300pix.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "Carl Friedrich Gauss",
Picture = PREFIX +
"9/9b/Carl_Friedrich_Gauss.jpg" +
"/225px-Carl_Friedrich_Gauss.jpg"
}
);
this._thumbnails.Add(
new Thumbnail {
Name = "J. Robert Oppenheimer",
Picture = PREFIX +
"0/03/JROppenheimer-LosAlamos.jpg" +
"/200px-JROppenheimer-LosAlamos.jpg"
}
);

// Assign collection to CoverFlow control
this.CoverFlow.ItemsSource = _thumbnails;
}
}
public class Thumbnail {
public string Name { get; set; }
public string Picture { get; set; }
}
}


The result of this code is a functional coverflow control as shown below.



Plain cover flow



The control is excellent for presenting a catalog of information and also providing an organic look and feel.  The following two snippet will demonstrate how to add depth to this control.  First, define a transitional background.



<Grid>
<
Grid.Background>
<
LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<
GradientStop Color="#000000" Offset="0.0"/>
<
GradientStop Color="#000000" Offset="0.6"/>
<
GradientStop Color="#131212" Offset="0.7"/>
<
GradientStop Color="#3A3535" Offset="0.8"/>
<
GradientStop Color="#625A5A" Offset="0.9"/>
<
GradientStop Color="#808080" Offset="1.0"/>
</
LinearGradientBrush>
</
Grid.Background>
<
c:CoverFlowControl x:Name="CoverFlow" Margin="0,10,0,0">
<!-- omitted for clarity -->
</c:CoverFlowControl>
</
Grid>


This gives the illusion that the coverflow items (images in this case) are residing on a surface with a little perspective.



Cover flow with background



And lastly, to the complete the visual effect, lets add a reflection.  This is achieved by adding a second image to the coverflow item data template.  A RenderTransfrom and OpacityMask are used to flip and fade the image respectively.



<c:CoverFlowControl x:Name="CoverFlow" Margin="0,10,0,0">
<
c:CoverFlowControl.ItemTemplate>
<
DataTemplate>
<
Grid>
<
Image Source="{Binding Path=Picture, Mode=OneWay}"
Height="300"
Stretch="UniformToFill"
/>
<
TextBlock Text="{Binding Path=Name, Mode=OneWay}"
Foreground="White"
HorizontalAlignment="Center"
FontSize="12"
/>
<
Image Source="{Binding Path=Picture, Mode=OneWay}"
Height="300"
Stretch="UniformToFill"
RenderTransformOrigin="0.5,1.0">
<
Image.RenderTransform>
<
TransformGroup>
<
ScaleTransform ScaleY="-1"/>
<
TranslateTransform Y="3"/>
</
TransformGroup>
</
Image.RenderTransform>
<
Image.OpacityMask>
<
LinearGradientBrush StartPoint="0.5,0"
EndPoint="0.5,1">
<
GradientStop Color="#00000000" Offset="0.0"/>
<
GradientStop Color="#00000000" Offset="0.7"/>
<
GradientStop Color="#FFFFFFFF" Offset="1.0"/>
</
LinearGradientBrush>
</
Image.OpacityMask>
</
Image>
</
Grid>
</
DataTemplate>
</
c:CoverFlowControl.ItemTemplate>
</
c:CoverFlowControl>


The result is an attractive clowflow with reflection.



Cover flow with background and reflection



There are two alternatives to this technique that you may want to consider.  The first is to use a pixel shader in Silverlight 3, Steve from Cellbi describes how to create a reflection pixel shader in this post.  The second is to make use of Silverlight 3’s WriteableBitmap class to generate a reflection.  Jeff Prosise from Wintellect describes the technique in this post.



The source code for this sample application is here:

http://cid-dd16c3f34f4d913e.skydrive.live.com/self.aspx/Kiwigis/CoverFlowWithReflection.zip

ESRI launches Mapping For Everyone website

Today ESRI announced the launch of a new website entitled Mapping for Everyone.  The site features an innovative four step web page for creating (and sharing) demographic maps.  Developers can experiment with the free JavaScript, Flex and Silverlight APIs or browse user samples.  Lastly, try ESRI’s free virtual globe called ArcGIS Explorer.
http://www.esri.com/mapping

Mapping for Everyone

Tag Map Magnifier for Microsoft Surface

This video demonstrates a new proof-of-concept developed by the Applications Prototype Lab in Redlands, California for the Microsoft Surface.

The application was developed using ESRI’s ArcGIS API for WPF and utilizes Surface-specific tags to act as virtual map magnifiers.  Tags are made up of a collection of domino-like black dots and are uniquely identified by the Surface device.  Developers can retrieve the tag position, identifier code and orientation.

The lab used the tags to add additional Map UIElements to the display.  As the user manipulates the tag, the magnifier map is repositioned and its map extent updated.  The map insets initially have same scale as the base map, a small scrollbar is provided to allow the user to magnify the map (or “zoom in”).

Because tags are uniquely identified, if a user removes a tag and then places it back on the table, we are able to restore previous settings such as the map magnifier’s size and relative scale.

Dynamic Charting for ArcGIS Desktop

This post describes a new sample published by ESRI’s Application Prototype Lab and inspired by Jack Dangermond geodesign presentation at the 2009 ESRI International User Conference.

Dynamic Charting for ArcGIS Desktop is a free sample (with source code) available from the ESRI code gallery.  The sample summarizes a layer’s features based on the length/area and grouped by unique values from the renderer.  The differentiating factor between this sample and the out-of-the-box charting tools is that this sample updates dynamically even in an edit session.

Dynamic Charting for ArcGIS Desktop 

Download

How to create a data report with ArcGIS Diagrammer

ArcGIS Diagrammer is productivity tool for ESRI’s ArcGIS Desktop users.  Diagrammer is primarily used to create or view geodatabase designs in a graphical editor.  This post will examine data reporting, a feature of Diagrammer that might be useful to a wide variety of ArcGIS Desktop users.

Let’s say that you or your organization has an existing geodatabase.  You may want to ask:

  1. Does my geodatabase have any empty feature datasets?
  2. Does my geodatabase have any feature classes with no data?
  3. Does my geodatabase have any subtypes with no data?
  4. Does my geodatabase have any feature classes with holes?

Diagrammer’s data reporter will help answer these questions.  Below is a short walk-through of creating a data report for a sample geodatabase that is included with ESRI’s ArcTutor product.

After starting ArcGIS Diagrammer, click Tools > Data Report.

A new tab will be added to the application called Data Report.  If the Properties Window is not visible then click View > Properties.  In the Properties Window, click the ellipsis () button next to the Workspace property.

The ellipsis button will launch a dialog for navigating to (and selecting) a geodatabase or SDE connection.  All geodatabase types are supported.

The selected geodatabase will be scanned for feature datasets, feature classes and subtypes.  This may take a few seconds or minutes depending on the size and complexity of the geodatabase.  When the scanning is complete a HTML report will be presented in the Data Report tab.

The report includes a header table and details about all feature classes, tables and subtypes.  Most useful is the number of features/rows per feature class, table and subtype.  Lastly, the report includes a small thumbnail representation of the data that, by default, hyperlinks to a larger image.

Data reports can be sent to a local printer/plotter or virtual printer should you wish to create a PDF document.  Alternatively, reports can be exported to a new HTML document.  To do so, click File > Export.

The save as dialog that appears will prompt you for the name and type of web document to create.  By default, “web archive” is selected.  We recommend you select “webpage, complete” as this will make a copy of the thumbnail images.  The only disadvantage of exporting a report to HTML is that the larger linked images will not included in the output location.  To prevent this, you can disable the creation of the larger images in the options dialog (see below).

This is an example of an export data report displayed in Windows Explorer.

When the exported HTML data report is viewed in a web browser, it looks identical to the report in ArcGIS Diagrammer.

Some options are provided to change the look and feel of data reports.  To display the Diagrammer options dialog, click Tools > Options.

The data report options are located under the Report > Data tab.  Most options are related to the font and the thumbnail images.

In the screenshot below I modified the font to be “Segoe Print” and increased the size of the small image to 200x200 and removed the larger linked image (Show Large Image = False).

That concludes this brief walkthrough of creating a data report with ArcGIS Diagrammer.  Diagrammer is a free download from ArcScripts and includes full source code.

List of other online tutorials: