主要参照了DevExpress的PhotoGallery实例的实现。
效果如下:
照片墙核心代码如下:
PhotoGallery.xaml
<local:CarouselDemoModule x:Class="PictureMagic.PhotoGallery" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dxca="http://schemas.devexpress.com/winfx/2008/xaml/carousel" xmlns:dxdb="http://schemas.devexpress.com/winfx/2008/xaml/demobase" xmlns:local="clr-namespace:PictureMagic" xmlns:collection="clr-namespace:System.Collections;assembly=mscorlib" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" > <dxdb:DemoModuleControl> <Grid ClipToBounds="False" Background="#FFB6C1"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition Height="80" /> </Grid.RowDefinitions> <dxca:CarouselPanel RenderOptions.BitmapScalingMode="HighQuality" x:Name="carousel" AnimationTime="500" VisibleItemCount="9" AttractorPointIndex="4" PathSizingMode="Stretch" PathPadding="10,5,10,20" IsAutoSizeItem="True" ClipToBounds="True" PathVisible="False" IsInvertedDirection="True" Grid.RowSpan="2" IsRepeat="True" ItemSize="100,100" > <dxca:CarouselPanel.Resources> <ControlTemplate x:Key="itemTemplate" TargetType="{x:Type ContentControl}"> <Grid VerticalAlignment="Center"> <Border Margin="3,3,0,0" Background="Black" Opacity="0.25" CornerRadius="1" /> <Border Margin="0,0,3,3" Padding="4" BorderBrush="#5F000000" BorderThickness="1" Background="White"> <Image Source="{Binding Path=DataContext, RelativeSource={RelativeSource TemplatedParent}}" Stretch="Uniform" /> </Border> </Grid> </ControlTemplate> <Style TargetType="{x:Type FrameworkElement}" x:Key="itemStyle"> <Setter Property="RenderTransformOrigin" Value="0.5, 0.5" /> <Setter Property="Opacity" Value="{Binding Path=(dxca:CarouselPanel.Parameters).Opacity, RelativeSource={RelativeSource Self}}" /> <Setter Property="Panel.ZIndex" Value="{Binding Path=(dxca:CarouselPanel.Parameters).ZIndex, Converter={local:DoubleToIntConverter}, RelativeSource={RelativeSource Self}}" /> <Setter Property="RenderTransform"> <Setter.Value> <TransformGroup> <ScaleTransform ScaleX="{Binding Path=(dxca:CarouselPanel.Parameters).Scale, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContentControl}}}" ScaleY="{Binding Path=(dxca:CarouselPanel.Parameters).Scale, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContentControl}}}" /> <TranslateTransform X="{Binding Path=(dxca:CarouselPanel.Parameters).OffsetX, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContentControl}}}" Y="{Binding Path=(dxca:CarouselPanel.Parameters).OffsetY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContentControl}}}" /> </TransformGroup> </Setter.Value> </Setter> </Style> </dxca:CarouselPanel.Resources> <dxca:CarouselPanel.ParameterSet> <dxca:ParameterCollection> <dxca:Parameter Name="Opacity" DistributionFunction="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type dxca:CarouselPanel}, ResourceId=Linear3PConvexNr}}" /> <dxca:Parameter Name="Scale" DistributionFunction="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type dxca:CarouselPanel}, ResourceId=Linear3PConvexNr}}" /> <dxca:Parameter Name="ZIndex" DistributionFunction="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type dxca:CarouselPanel}, ResourceId=Linear3PConvexERIntMax}}" /> </dxca:ParameterCollection> </dxca:CarouselPanel.ParameterSet> <dxca:CarouselPanel.ItemMovingPath> <PathGeometry Figures="M255,0 C352.86864,0.5 454.5,61.389274 454.5,136.5 C454.5,211.61073 352.86864,272.5 227.5,272.5 C102.13136,272.5 0.5,211.61073 0.5,136.5 C0.5,61.389274 102.13136,0.5 200,0.5 " /> </dxca:CarouselPanel.ItemMovingPath> </dxca:CarouselPanel> <dxdb:ImageControl Margin="30,30,30,0" Source="{Binding ElementName=carousel, Path=ActiveItem.DataContext}" VerticalAlignment="Center" HorizontalAlignment="Center" /> <dxca:CarouselNavigator VerticalAlignment="Center" HorizontalAlignment="Center" MinHeight="24" MinWidth="300" Grid.Row="2" Carousel="{Binding ElementName=carousel}" /> </Grid> </dxdb:DemoModuleControl> </local:CarouselDemoModule>
PhotoGallery.xaml.cs
using System.Windows; using System.Windows.Controls; using DevExpress.Xpf.Carousel; using System.Collections.Generic; namespace PictureMagic { public partial class PhotoGallery : CarouselDemoModule { private List<PicutureInfo> m_picureInfoList = null; public PhotoGallery() { InitializeComponent(); m_picureInfoList = new List<PicutureInfo>(); } protected override void AddItems(string path, ItemType it, CarouselPanel carousel) { var items = CreateItems(path, it); foreach (var item in items) { ContentControl control = new ContentControl(); control.Template = carousel.Resources["itemTemplate"] as ControlTemplate; control.Style = carousel.Resources["itemStyle"] as Style; control.DataContext = ((Image)item).Source; carousel.Children.Add(control); } } public void ShowNextImage() { carousel.MoveNext(); } public void SearchImage(string path) { carousel.Children.Clear(); AddItems(path, ItemType.BinaryImage, carousel); } } }
CarouselDemoModule.cs
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using DevExpress.Utils; using DevExpress.Xpf.Carousel; using DevExpress.Xpf.DemoBase; namespace PictureMagic { public class CarouselDemoModule : DemoModule { static CarouselDemoModule() { Type ownerType = typeof(CarouselDemoModule); } public override void OnApplyTemplate() { base.OnApplyTemplate(); CommandManager.InvalidateRequerySuggested(); } protected virtual List<FrameworkElement> CreateItems(string path, ItemType it) { ContentLoadHelper contentLoadHelper = new ContentLoadHelper(); contentLoadHelper.Path = path; var itemList = new List<FrameworkElement>(contentLoadHelper.LoadItems(it).ToArray()); for (int i = 0; i < itemList.Count; i++) { itemList[i].Name = "Item" + i.ToString(); ((Image)itemList[i]).Stretch = System.Windows.Media.Stretch.Fill; } return itemList; } protected virtual void AddItems(string path, ItemType it, CarouselPanel carousel) { var itemList = CreateItems(path, it); foreach (var item in itemList) { item.Name = "item" + carousel.Children.Count; carousel.Children.Add(item); } } } }
Utils.cs
using System; using System.Collections.Generic; using System.IO; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Data; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace PictureMagic { public enum ItemType { BinaryImage, DrawingImage } public class ContentLoadHelper { public string Path { get; set; } public ContentLoadHelper() { } public List<FrameworkElement> LoadItems(ItemType it) { LoadDelegate loadDelegate = null; switch (it) { case ItemType.BinaryImage: loadDelegate = LoadImage; break; case ItemType.DrawingImage: // loadDelegate = LoadDrawingImage; break; } var items = new List<FrameworkElement>(); if (loadDelegate != null) { DirectoryInfo folder = new DirectoryInfo(Path); foreach (FileInfo file in folder.GetFiles("*.*")) { if (IsPhotoFile(file.Extension)) { items.Add(loadDelegate(file.FullName)); } } } return items; } private bool IsPhotoFile(string extension) { string[] exArray = { ".PNG", ".JPG", ".BMP", ".GIF", ".JPEG" }; foreach (string strExe in exArray) { if (extension.ToUpper().Equals(strExe)) { return true; } } return false; } public delegate FrameworkElement LoadDelegate(string strPath); public Image LoadDrawingImage(Stream stream) { var rd = (ResourceDictionary)XamlReader.Load(stream); var di = (DrawingImage)rd["Layer_1"]; return new Image() { Source = di }; } public Image LoadImage(string strPath) { var image = new Image(); image.Source = new BitmapImage(new Uri(strPath)); return image; } } public class DoubleToIntConverter : MarkupExtension, IValueConverter { public override object ProvideValue(IServiceProvider serviceProvider) { return this; } #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(int)) throw new InvalidOperationException(); return (int)((double)value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } #endregion } }