Download Source Code

Window1.xaml

<Window x:Class="NativeFileTypeViewer.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:NativeFileTypeViewer"
    Title="Window1" Height="446" Width="637">
    <Window.Resources>
        <DataTemplate x:Key="FilenameTemplate">
            <Grid Margin="3,3,3,3">
                <Grid.Resources>
                    <local:FilenameDescriptionConverter x:Key="descriptionConverter" />
                    <local:FullPathFilenameConverter x:Key="filenameConverter" />
                    <local:FilenameIconImageConverter x:Key="iconConverter" Use32PixelIcon="True" />
                </Grid.Resources>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20" />
                    <RowDefinition Height="20" />
                </Grid.RowDefinitions>
                <Image Source="{Binding Converter={StaticResource iconConverter}}" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Height="32" Width="32" />
                
                <TextBlock Text="{Binding Converter={StaticResource filenameConverter}}" Grid.Column="1" FontWeight="Bold" />
                <TextBlock Text="{Binding Converter={StaticResource descriptionConverter}}" Grid.Column="1" Grid.Row="1" Foreground="DarkGray" />
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid Margin="5,5,5,5">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="80" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBox x:Name="Folder" VerticalAlignment="Center">C:\</TextBox>
        <Button Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Click="load_Click">Load Files</Button>
        
        <ListBox x:Name="Files" Grid.Row="1" Grid.ColumnSpan="2" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource FilenameTemplate}" />
    </Grid>
</Window>

Window1.xaml.cs

using System;
...

using io = System.IO;

namespace NativeFileTypeViewer
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            this.Folder.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        }

        private void load_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string[] files = io::Directory.GetFiles(this.Folder.Text);
                this.Files.ItemsSource = files;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}

FilenameIconImageConverter.cs

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;

namespace Com.Scientiae.SimpleSafe
{
    [ValueConversion(typeof(string), typeof(ImageSource))]
    public class FilenameIconImageConverter : IValueConverter
    {
        private static System.Collections.Generic.Dictionary<string, ImageSource> _internalCache;

        public bool Use32PixelIcon { get; set; }

        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            ImageSource source = null;
            lock (this)
            {
                if (_internalCache == null)
                    _internalCache = new System.Collections.Generic.Dictionary<string, ImageSource>();

                string ext = Path.GetExtension(value.ToString());
                if (_internalCache.ContainsKey(ext + (Use32PixelIcon ? "32" : "16")))
                {
                    return _internalCache[ext + (Use32PixelIcon ? "32" : "16")];
                }
                else
                {
                    string resourcePath = Path.Combine(Path.GetTempPath(), "file" + ext);
                    FileInfo resource = new FileInfo(resourcePath);
                    try
                    {
                        if (!resource.Exists)
                        {
                            using (StreamWriter strm = resource.CreateText())
                                strm.Close();
                        }

                        SHFILEINFO shinfo = new SHFILEINFO();
                        if (Use32PixelIcon)
                            Win32.SHGetFileInfo(resource.FullName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
                        else
                            Win32.SHGetFileInfo(resource.FullName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);

                        Icon fileIcon = Icon.FromHandle(shinfo.hIcon);
                        using (MemoryStream memStream = new MemoryStream())
                        {
                            Bitmap iconBitmap = fileIcon.ToBitmap();
                            iconBitmap.Save(memStream, ImageFormat.Png);

                            memStream.Seek(0, SeekOrigin.Begin);
                            PngBitmapDecoder bitmapDecoder = new PngBitmapDecoder(memStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
                            source = bitmapDecoder.Frames[0];
                            source.Freeze();
                        }
                    }
                    finally
                    {
                        resource.Delete();
                    }
                    
                    if (source != null)
                        _internalCache.Add(ext + (Use32PixelIcon ? "32" : "16"), source);
                }
            }
            return source;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}

Win32.cs

using System;
using System.Runtime.InteropServices;

namespace NativeFileTypeViewer
{
    class Win32
    {
        public const uint SHGFI_DISPLAYNAME = 0x00000200;
        public const uint SHGFI_TYPENAME = 0x400;
        public const uint SHGFI_ICON = 0x100;
        public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
        public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

        [DllImport("shell32.dll")]
        public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
    }
}

SHFILEINFO.cs

using System;
using System.Runtime.InteropServices;

namespace NativeFileTypeViewer
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SHFILEINFO
    {
        public IntPtr hIcon;
        public IntPtr iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    }
}