WPF 照片墙的实现

时间:2024-03-17 14:20:34

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