What we need:
1. Imdb Services
(http://www.codeplex.com/imdb/Release/ProjectReleases.aspx?ReleaseId=11705)
2. ElementFlow from FluidKit library
(http://www.codeplex.com/fluidkit/SourceControl/ListDownloadableCommits.aspx)
Create a new Wpf Application project in Visual Studio 2008.
Add two libraries in the project.
Design your Application.
A Glass Button Template:
<ControlTemplate x:Key="GlassButton" TargetType="{x:Type Button}"> <ControlTemplate.Resources>
<Storyboard x:Key="Timeline1"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="glow" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/> </DoubleAnimationUsingKeyFrames>
</Storyboard> <Storyboard x:Key="Timeline2">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="glow" Storyboard.TargetProperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames> </Storyboard>
</ControlTemplate.Resources> <Border BorderBrush="#FFFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="border" Background="#7F000000" BorderBrush="#FF000000" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4"> <Grid>
<Grid.RowDefinitions> <RowDefinition Height="0.507*"/>
<RowDefinition Height="0.493*"/> </Grid.RowDefinitions>
<Border Opacity="0" HorizontalAlignment="Stretch" x:Name="glow" Width="Auto" Grid.RowSpan="2" CornerRadius="4,4,4,4"> <Border.Background>
<RadialGradientBrush> <RadialGradientBrush.RelativeTransform>
<TransformGroup> <ScaleTransform ScaleX="1.702" ScaleY="2.243"/>
<SkewTransform AngleX="0" AngleY="0"/> <RotateTransform Angle="0"/>
<TranslateTransform X="-0.368" Y="-0.152"/> </TransformGroup>
</RadialGradientBrush.RelativeTransform> <GradientStop Color="#B28DBDFF" Offset="0"/>
<GradientStop Color="#008DBDFF" Offset="1"/> </RadialGradientBrush>
</Border.Background> </Border>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" Grid.RowSpan="2"/> <Border HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="shine" Width="Auto" CornerRadius="4,4,0,0">
<Border.Background> <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028">
<GradientStop Color="#99FFFFFF" Offset="0"/> <GradientStop Color="#33FFFFFF" Offset="1"/>
</LinearGradientBrush> </Border.Background>
</Border> </Grid>
</Border> </Border>
<ControlTemplate.Triggers> <Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" TargetName="shine" Value="0.4"/> <Setter Property="Background" TargetName="border" Value="#CC000000"/>
<Setter Property="Visibility" TargetName="glow" Value="Hidden"/> </Trigger>
<Trigger Property="IsMouseOver" Value="True"> <Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Timeline1}"/> </Trigger.EnterActions>
<Trigger.ExitActions> <BeginStoryboard x:Name="Timeline2_BeginStoryboard" Storyboard="{StaticResource Timeline2}"/>
</Trigger.ExitActions> </Trigger>
</ControlTemplate.Triggers> </ControlTemplate>
<Canvas VerticalAlignment="Top" Height="63.319"> <Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFFFFFFF" Offset="0.022"/>
<GradientStop Color="#FFEC9F02" Offset="0.991"/> </LinearGradientBrush>
</Canvas.Background> <TextBox x:Name="txttitle" Width="267.681" Height="28.985" Canvas.Left="75.71" FontSize="16" Canvas.Top="22.174" Text="" TextWrapping="Wrap"/>
<TextBlock Width="Auto" Height="37.681" FontSize="22" Foreground="#FF1C1C1C" Text="Title:" TextWrapping="Wrap" Canvas.Left="8" Canvas.Top="22.174"/> <Button Click="Button_Click" x:Name="btnSearch" Width="127" Height="42.279" Content="Search" Template="{DynamicResource GlassButton}" Cursor="Hand" FontSize="16" Foreground="#FFFFFFFF" Canvas.Left="350" Canvas.Top="16.695">
<Button.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFFFF" Offset="0" /> <GradientStop Color="#FF9EFF8D" Offset="0.482" />
<GradientStop Color="#FFADFF8D" Offset="1" /> </LinearGradientBrush>
</Button.Background> </Button>
</Canvas>
Region 2 – ElementFlow Control
<ItemsControl x:Name="_itemsControl" ItemsSource="{StaticResource TestDataSource}" ItemTemplate="{StaticResource TestDataTemplate_Reflection}" Margin="0,63.321,392,0" Cursor="Hand">
<ItemsControl.ItemsPanel> <ItemsPanelTemplate>
<Controls:ElementFlow x:Name="ElementFlow" Focusable="True"
TiltAngle="{Binding Value, ElementName=_tiltAngleSlider}" ItemGap="{Binding Value, ElementName=_itemGapSlider}"
FrontItemGap="{Binding Value, ElementName=_frontItemGapSlider}" PopoutDistance="{Binding Value, ElementName=_popoutDistanceSlider}"
ElementWidth="400" ElementHeight="600"
HasReflection="False" Background="Black">
<Controls:ElementFlow.Camera> <PerspectiveCamera FieldOfView="60"
Position="0,1,4" LookDirection="0,-1,-4"
UpDirection="0,1,0" /> </Controls:ElementFlow.Camera>
</Controls:ElementFlow> </ItemsPanelTemplate>
</ItemsControl.ItemsPanel> </ItemsControl> <TextBlock Text="F12 to switch views"
Foreground="White" FontWeight="Bold"
VerticalAlignment="Top" Margin="402,84,402,0" Height="13.277" />
Region 3 – Movie Details Control
<UserControl x:Class="ucDetails" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="Auto" Height="Auto" xmlns:d=http://schemas.microsoft.com/expression/blend/2008 xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006 mc:Ignorable="d" d:DesignWidth="354" d:DesignHeight="573"> <Grid Height="Auto" Width="Auto"> <Label Height="26.667" HorizontalAlignment="Left" Margin="0,14,0,0" x:Name="Label1" VerticalAlignment="Top" Width="Auto" Content="Title:" FontSize="14"/> <Label Height="27" HorizontalAlignment="Left" Margin="0,44.667,0,0" x:Name="Label2" VerticalAlignment="Top" Width="Auto" Content="Year:" FontSize="14"/> <Label Height="25" HorizontalAlignment="Left" Margin="0,80,0,0" x:Name="Label3" VerticalAlignment="Top" Width="Auto" Content="Director:" FontSize="14"/> <Label Height="26" HorizontalAlignment="Left" Margin="0,113.333,0,0" x:Name="Label4" VerticalAlignment="Top" Width="Auto" Content="Genres:" FontSize="14"/> <Label Height="28.667" HorizontalAlignment="Left" Margin="0,147.666,0,0" x:Name="Label5" VerticalAlignment="Top" Width="Auto" Content="Rating:" FontSize="14"/> <Label Height="27.333" HorizontalAlignment="Left" Margin="0,180.333,0,0" x:Name="Label6" VerticalAlignment="Top" Width="Auto" Content="Studio:" FontSize="14"/> <Label HorizontalAlignment="Left" Margin="0,225.333,0,0" x:Name="Label7" Width="Auto" Height="Auto" Content="Plot:" FontSize="14" d:LayoutOverrides="Height" VerticalAlignment="Top"/> <Label Height="26.667" Margin="68,14,0,0" x:Name="txttitle" VerticalAlignment="Top" Content="..." FontSize="14"/> <Label Height="27" Margin="68,44.667,0,0" x:Name="txtyear" VerticalAlignment="Top" Content="..." FontSize="14"/> <Label Height="25" Margin="67.847,80,0.153,0" x:Name="txtdirector" VerticalAlignment="Top" Content="..." FontSize="14"/> <Label Height="26" Margin="68,113.333,0,0" x:Name="txtgenres" VerticalAlignment="Top" Content="..." FontSize="14"/> <Label Height="28.667" Margin="67.847,147.666,0.153,0" x:Name="txtrating" VerticalAlignment="Top" Content="..." FontSize="14"/> <Label Height="27.333" Margin="68,176.333,0,0" x:Name="txtstudio" VerticalAlignment="Top" Content="..." FontSize="14"/> <TextBox Margin="67.846,233.332,0,-0.002" x:Name="txtplot" IsReadOnly="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" AcceptsReturn="True" AcceptsTab="True" TextWrapping="WrapWithOverflow" /> </Grid> </UserControl>
Add UserControl to Main Window.
<local:ucDetails x:Name="DetailsControl" Margin="0,63.319,0,-0.002" Width="394" HorizontalAlignment="Right"/>
Data Template & Data Source for ElementFlow Control
<local:StringCollection x:Key="TestDataSource" />
<DataTemplate x:Key="TestDataTemplate" DataType="{x:Type sys:String}"> <Border x:Name="ElementVisual" Background="White" Padding="5" BorderThickness="5" BorderBrush="LightGray" Grid.Row="0"> <Image Source="{Binding}" Stretch="Fill" /> </Border> </DataTemplate>
Add a new class “StringCollection”
1: Imports System.Collections.ObjectModel 2:
3: 4: Public Class StringCollection
5: Inherits ObservableCollection(Of String) 6: Public Sub New()
7: 8: End Sub
9: End Class 10:
Main Code.
1. Private Variables
1: #Region "Private Variables" 2: Private _elementFlow As ElementFlow
3: Private _randomizer As New Random() 4: Private _dataSource As StringCollection
5: Private _views As ViewStateBase() = {New CoverFlow(), New Carousel(), New TimeMachine2(), New ThreeLane(), New VForm(), New TimeMachine(), _ 6: New RollerCoaster(), New Rolodex()}
7: Private _viewIndex As Integer = 0 8: Dim WithEvents ImdbServ As New ImdbServices.Imdb
9: Private MovieCounter As Integer = 0 10: Private ImdbMoviesIds As List(Of Long)
11: Private ImdbMovies As List(Of ImdbServices.Movie) 12:
13: #End Region
2. Form Load – Initialize Collections, Get ElementFlow control
1: #Region "Form Load" 2:
3: Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded 4: ' Get reference to ElementFlow
5: Dim obj As DependencyObject = VisualTreeHelper.GetChild(_itemsControl, 0) 6: While (TypeOf obj Is ElementFlow) = False
7: obj = VisualTreeHelper.GetChild(obj, 0) 8: End While
9: _elementFlow = TryCast(obj, ElementFlow) 10: _elementFlow.SelectedIndex = 0
11: 12: _dataSource = New StringCollection()
13: _dataSource.Clear() 14:
15: _itemsControl.ItemsSource = _dataSource 16:
17: ImdbServ = New ImdbServices.Imdb 18: ImdbMoviesIds = New List(Of Long)
19: ImdbMovies = New List(Of ImdbServices.Movie) 20: End Sub
21: 22: #End Region
3. ElementFlow control events
1: #Region "Element Flow Events" 2:
3: Protected Overloads Overrides Sub OnKeyDown(ByVal e As KeyEventArgs) 4: If e.Key = Key.F12 Then
5: _viewIndex = (_viewIndex + 1) Mod _views.Length 6: _elementFlow.CurrentView = _views(_viewIndex)
7: End If 8: End Sub
9: 10:
11: Private Sub RemoveCard(ByVal sender As Object, ByVal args As RoutedEventArgs) 12: If _elementFlow.Children.Count > 0 Then
13: _dataSource.RemoveAt(_randomizer.[Next](_dataSource.Count)) 14:
15: End If 16: End Sub
17: 18: Private Sub AddCard(ByVal item As String)
19: Dim index As Integer = _randomizer.[Next](_dataSource.Count) 20: _dataSource.Insert(index, item)
21: End Sub 22:
23: #End Region
4. Button Search
1: #Region "Button Search" 2:
3: Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) 4: _dataSource.Clear()
5: ImdbMovies.Clear() 6: ImdbMoviesIds.Clear()
7: ImdbServ.SearchMovieAsync(Me.txttitle.Text) 8: End Sub
9: 10:
11: Private Sub ImdbServ_SearchResultsDownloaded(ByVal M As ImdbServices.MoviesResultset) Handles ImdbServ.SearchResultsDownloaded 12:
13: If M.PopularTitles.Count > 0 Then 14: For Each Movie As ImdbServices.Movie In M.PopularTitles
15: ImdbMoviesIds.Add(Movie.ImdbID) 16: Next
17: End If 18:
19: If M.PartialMatches.Count > 0 Then 20: For Each Movie As ImdbServices.Movie In M.PartialMatches
21: ImdbMoviesIds.Add(Movie.ImdbID) 22: Next
23: End If 24:
25: If M.ExactMatches.Count > 0 Then 26: For Each Movie As ImdbServices.Movie In M.ExactMatches
27: ImdbMoviesIds.Add(Movie.ImdbID) 28: Next
29: End If 30:
31: MovieCounter = 0 32: If ImdbMoviesIds.Count > 0 Then
33: ImdbServ.GetMovieInfoAsync(ImdbMoviesIds(MovieCounter)) 34: MovieCounter += 1
35: End If 36:
37: End Sub 38:
39: 40: Private Sub ImdbServ_MovieInfoDownloaded(ByVal M As ImdbServices.Movie) Handles ImdbServ.MovieInfoDownloaded
41: 42: ImdbMovies.Add(M)
43: 44: If Not M.ImageURL = "" Then
45: AddCard(M.ImageURL) 46: End If
47: 48: If MovieCounter < ImdbMoviesIds.Count Then
49: ImdbServ.GetMovieInfoAsync(ImdbMoviesIds(MovieCounter)) 50: MovieCounter += 1
51: ChangeSelectedIndex() 52: End If
53: 54:
55: End Sub 56:
57: #End Region
5. Fill Details
1: #Region "Fill Details" 2:
3: Private Sub ChangeSelectedIndex() 4:
5: 'Fill Details 6: Dim index As Integer = _elementFlow.SelectedIndex
7: 8: Dim M = From c In ImdbMovies Where c.ImageURL = _dataSource.Item(index) Select c
9: Dim SelectedMovie As ImdbServices.Movie = M.First 10:
11: Me.DetailsControl.txttitle.Content = SelectedMovie.Title 12: Me.DetailsControl.txtyear.Content = SelectedMovie.Year.ToString
13: 14: If SelectedMovie.Directors.Count > 0 Then Me.DetailsControl.txtdirector.Content = SelectedMovie.Directors(0).Name
15: 16: Me.DetailsControl.txtgenres.Content = ""
17: For Each item As String In SelectedMovie.Genres 18: Me.DetailsControl.txtgenres.Content += item + ","
19: Next 20: Me.DetailsControl.txtrating.Content = SelectedMovie.Rating
21: Me.DetailsControl.txtplot.Text = SelectedMovie.Description 22:
23: Me.DetailsControl.txtstudio.Content = If(SelectedMovie.Studios.Count > 0, SelectedMovie.Studios(0), "") 24:
25: 26: End Sub
27: 28: Private Sub _itemsControl_MouseLeftButtonUp(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles _itemsControl.MouseLeftButtonUp
29: ChangeSelectedIndex() 30: End Sub
31: 32: Private Sub _itemsControl_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Input.MouseWheelEventArgs) Handles _itemsControl.MouseWheel
33: ChangeSelectedIndex() 34: End Sub
35: 36: #End Region