WPF Cover Flow Tutorial : Part 5

15 篇文章 0 订阅
After Part 4, we will partly refactor the code to build a custom component.

We define a new assembly called FlowComponent where we will move most of the code. First, the c# code will be part of a new class called FlowControl. This class herits from UserControl :
  1. using[...]  
  2. namespace Ded.Tutorial.Wpf.CoverFlow.Part5.FlowComponent  
  3. {  
  4.     public partial class FlowControl : UserControl  
  5.     {  
  6.         #region Fields  
  7.         private int index;  
  8.         private readonly List<Cover> coverList = new List<Cover>();  
  9.         #endregion  
  10.         #region Private stuff  
  11.         private void RotateCover(int pos)[...]  
  12.         private void UpdateIndex(int newIndex)[...]  
  13.         private void viewPort_MouseDown(object sender, MouseButtonEventArgs e)[...]  
  14.         #endregion  
  15.         public FlowControl()  
  16.         {  
  17.             InitializeComponent();  
  18.         }  
  19.         public void Load(string imagePath)  
  20.         {  
  21.             coverList.Clear();  
  22.             var imageDir = new DirectoryInfo(imagePath);  
  23.             int doneImages = 0;  
  24.             foreach (FileInfo image in imageDir.GetFiles("*.jpg"))  
  25.             {  
  26.                 var cover = new Cover(image.FullName, doneImages++);  
  27.                 coverList.Add(cover);  
  28.                 visualModel.Children.Add(cover);  
  29.             }  
  30.         }  
  31.         public void GoToNext()  
  32.         {  
  33.             if (index < coverList.Count - 1)  
  34.                 UpdateIndex(index + 1);  
  35.         }  
  36.         public void GoToPrevious()  
  37.         {  
  38.             if (index > 0)  
  39.                 UpdateIndex(index - 1);  
  40.         }  
  41.     }  
  42. }  
The code from the TestWindow constructor is included in a new method called Load. It will build covers with the images from one directory. We also provide two new methods GoToNext and GoToPrevious to navigate between covers.

This is the same in the xaml code : we migrate the Grid (its background) and the Viewport3D to our custom UserControl :
  1. <UserControl x:Class="Ded.Tutorial.Wpf.CoverFlow.Part5.FlowComponent.FlowControl"  
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.     Height="282" Width="490">  
  5.   <Grid ClipToBounds="True">  
  6.     <Grid.Background[...]>  
  7.     <Viewport3D x:Name="viewPort" Grid.Column="0" Grid.Row="0" ClipToBounds="False" MouseDown="viewPort_MouseDown">  
  8.       <Viewport3D.Camera[...]>  
  9.       <Viewport3D.Children[...]>  
  10.     </Viewport3D>  
  11.   </Grid>  
  12. </UserControl>  
We can set the size we want. It will be overriden in the owner component. We set the ClipToBounds property to True to avoid covers from exceeding the bounds of our component.

The Cover class is also moved to the FlowComponent assembly.

As we are creating a CoverFlow component, it is a good idea to deal with rectangle images. We update thePoint3D coordinates with the ImageSource size. The ImageSource will be stored as a class attribute.
  1. private readonly ImageSource imageSource;  
  2. private double RectangleDx()  
  3. {  
  4.     if (imageSource.Width > imageSource.Height)  
  5.         return 0;  
  6.     else  
  7.         return 1 - imageSource.Width / imageSource.Height;  
  8. }  
  9. private double RectangleDy()  
  10. {  
  11.     if (imageSource.Width > imageSource.Height)  
  12.         return 1 - imageSource.Height / imageSource.Width;  
  13.     else  
  14.         return 0;  
  15. }  
  16. private Geometry3D Tessellate()  
  17. {  
  18.     double dx = RectangleDx();  
  19.     double dy = RectangleDy();  
  20.     var p0 = new Point3D(-1 + dx, -1 + dy, 0);  
  21.     var p1 = new Point3D(1 - dx, -1 + dy, 0);  
  22.     var p2 = new Point3D(1 - dx, 1 - dy, 0);  
  23.     var p3 = new Point3D(-1 + dx, 1 - dy, 0);  
  24.     ...  
  25. }  
  26. private Geometry3D TessellateMirror()  
  27. {  
  28.     double dx = RectangleDx();  
  29.     double dy = RectangleDy();  
  30.     var p0 = new Point3D(-1 + dx, -3 + 3 * dy, 0);  
  31.     var p1 = new Point3D(1 - dx, -3 + 3 * dy, 0);  
  32.     var p2 = new Point3D(1 - dx, -1 + dy, 0);  
  33.     var p3 = new Point3D(-1 + dx, -1 + dy, 0);  
  34.     ...  
  35. }  
  36. public Cover(string imagePath, int pos)  
  37. {  
  38.     ...  
  39.     imageSource = LoadImageSource(imagePath);  
  40.     ...  
  41. }  
With this new improvement, it is possible to use the component to browse photos :
There is nothing much left in the TestWindow class. In the xaml code, after we've referenced our component assembly, we just use our FlowControl as main Content :
  1. <Window x:Class="Ded.Tutorial.Wpf.CoverFlow.Part5.TestWindow"  
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.     Title="WPF Coverflow" Width="512" Height="320" KeyDown="Window_KeyDown"  
  5.     xmlns:flow="clr-namespace:Ded.Tutorial.Wpf.CoverFlow.Part5.FlowComponent;assembly=Ded.Tutorial.Wpf.CoverFlow.Part5.FlowComponent">  
  6.   <flow:FlowControl x:Name="flow" Margin="0"></flow:FlowControl>  
  7. </Window>  
In the C# code, we just keep the Window_KeyDown method and the constructor :
  1. using System.Windows;  
  2. using System.Windows.Input;  
  3. namespace Ded.Tutorial.Wpf.CoverFlow.Part5  
  4. {  
  5.     public partial class TestWindow : Window  
  6.     {  
  7.         #region Private stuff  
  8.         private void Window_KeyDown(object sender, KeyEventArgs e)  
  9.         {  
  10.             switch (e.Key)  
  11.             {  
  12.                 case Key.Right:  
  13.                     flow.GoToNext();  
  14.                     break;  
  15.                 case Key.Left:  
  16.                     flow.GoToPrevious();  
  17.                     break;  
  18.             }  
  19.         }  
  20.         #endregion  
  21.         public TestWindow()  
  22.         {  
  23.             InitializeComponent();  
  24.             flow.Load(@"c:\_covers");  
  25.         }  
  26.     }  
  27. }  
That's it ! We've built a CoverFlow component reusable in other WPF applications. But this component needs improvements. We will add virtualization in the next part...

Download source. Continue with Part 6.

转载自:http://d3dal3.blogspot.com/2008/10/wpf-cover-flow-tutorial-part-5.html

版权归原作者所有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值