Displaying Images from a folder with details in WPF
Today I decided to write how to display images from a folder with details using WPF.
What is my motivation? This StackOverflow post:
http://stackoverflow.com/questions/13034911/create-control-instance-in-wpf
Here is my full example project: ImageList.zip
The first thing I did was create a new WPF Project in Visual Studio. After that I followed these steps.
- Created an Images folder in the project and added two images.
- Changed the images properties in Visual Studio to have a Build Action of Content and to only Copy if newer.
- Created an ImageDetails object.
- Created XAML for displaying the image using binding.
- Wrote code behind to load images from a folder, get the image details, and add them to a list. Note: I had to add a reference to System.Drawing to use System.Drawing.Image.
The Model.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ImageList.Model { public class ImageDetails { /// <summary> /// A name for the image, not the file name. /// </summary> public string Name { get; set; } /// <summary> /// A description for the image. /// </summary> public string Description { get; set; } /// <summary> /// Full path such as c:\path\to\image.png /// </summary> public string Path { get; set; } /// <summary> /// The image file name such as image.png /// </summary> public string FileName { get; set; } /// <summary> /// The file name extension: bmp, gif, jpg, png, tiff, etc... /// </summary> public string Extension { get; set; } /// <summary> /// The image height /// </summary> public int Height { get; set; } /// <summary> /// The image width. /// </summary> public int Width { get; set; } /// <summary> /// The file size of the image. /// </summary> public long Size { get; set; } } }
The XAML. Basically it is an ItemsControl with an ItemsTemplate and all the complexity and binding is in the ItemsTemplate.
<Window x:Class="ImageList.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded_1"> <Grid> <ItemsControl Name="ImageList" ItemsSource="{Binding ImageList}"> <ItemsControl.ItemTemplate> <DataTemplate> <Border BorderThickness="1" BorderBrush="#FFD0D1D7" Padding="5" Margin="10,10,0,0"> <StackPanel Orientation="Horizontal"> <!--image and dimensions--> <Grid Width="88" Height="55"> <Image Source="{Binding Path}"/> <TextBlock Background="#B2000000" Foreground="White" Height="16" TextAlignment="Center" VerticalAlignment="Bottom"> <TextBlock.Text> <MultiBinding StringFormat="{}{0}x{1}"> <Binding Path="Height"/> <Binding Path="Width"/> </MultiBinding> </TextBlock.Text> </TextBlock> </Grid> <!--name, type and size--> <StackPanel Orientation="Vertical" Margin="5,0,0,0" VerticalAlignment="Center"> <TextBlock Name="ImageName" Margin="1" Foreground="#FF787878" Text="{Binding FileName}"/> <TextBlock Name="ImageType" Margin="1" Foreground="#FF787878"> <TextBlock.Text> <MultiBinding StringFormat="Type: {0}"> <Binding Path="Extension"/> </MultiBinding> </TextBlock.Text> </TextBlock> <TextBlock Name="ImageSize" Margin="1" Foreground="#FF787878"> <TextBlock.Text> <MultiBinding StringFormat="Size: {0} Bytes"> <Binding Path="Size"/> </MultiBinding> </TextBlock.Text> </TextBlock> </StackPanel> </StackPanel> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Window>
The Code behind. Feel free to switch this to use MVVM if needed. I didn’t use MVVM only because this is an example only.
using ImageList.Model; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace ImageList { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded_1(object sender, RoutedEventArgs e) { string root = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string[] supportedExtensions = new[] { ".bmp", ".jpeg", ".jpg", ".png", ".tiff" }; var files = Directory.GetFiles(Path.Combine(root, "Images"), "*.*").Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower())); List<ImageDetails> images = new List<ImageDetails>(); foreach (var file in files) { ImageDetails id = new ImageDetails() { Path = file, FileName = Path.GetFileName(file), Extension = Path.GetExtension(file) }; BitmapImage img = new BitmapImage(); img.BeginInit(); img.CacheOption = BitmapCacheOption.OnLoad; img.UriSource = new Uri(file, UriKind.Absolute); img.EndInit(); id.Width = img.PixelWidth; id.Height = img.PixelHeight; // I couldn't find file size in BitmapImage FileInfo fi = new FileInfo(file); id.Size = fi.Length; images.Add(id); } ImageList.ItemsSource = images; } } }
It is in reality a great and useful piece of info. I aam glad that you just shared this
useful info with us. Please keep us informed like this.
Thanks for sharing.
This is great!, but what if i wanted to view the pictures horizontally not vertically ?
thanks for this awesome tutorial
Glad to be of help.