主要参照了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
}
}