ファイラーその4

アイコンをつける。
Win32apiのSHGetFileInfoを呼べるようにする

    [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;
    };

    class Win32
    {
        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);

        [DllImport("user32")]
        public static extern int DestroyIcon(IntPtr hIcon);
    }

ファイルパスからアイコン画像を得る。ObservableCollection

    class Item
    {
        public FileSystemInfo Info
        {
            set;
            get;
        }

        public String Name
        {
            get { return Info.Name; }
        }

        public String Length
        {
            get
            {
                var file = Info as FileInfo;
                if (file == null)
                {
                    return "";
                }
                else
                {
                    return file.Length.ToString();
                }
            }
        }

        public BitmapSource Bitmap
        {
            get
            {
                SHFILEINFO shinfo = new SHFILEINFO();
                var hImgLarge = Win32.SHGetFileInfo(Info.FullName, 0,
                    ref shinfo, (uint)Marshal.SizeOf(shinfo),
                    Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
                BitmapSource source = Imaging.CreateBitmapSourceFromHIcon(shinfo.hIcon, Int32Rect.Empty, null);
                Win32.DestroyIcon(shinfo.hIcon);
                return source;
            }
        }
    };

ListViewのDataTemplateにBitmapをバインディングする

        <ListView Grid.Row="1" ItemsSource="{Binding Path=Files}" AlternationCount="2">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="Name">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="*" />
                                        </Grid.ColumnDefinitions>
                                        <Image Grid.Column="0" Source="{Binding Path=Bitmap}" Margin="5,0,5,0" />
                                        <Label Grid.Column="1" Content="{Binding Path=Name}"/>
                                    </Grid>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Size">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Label Content="{Binding Path=Length}" HorizontalAlignment="Right"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView.Columns>
                </GridView>
            </ListView.View>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}"  >
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <EventSetter Event="MouseDoubleClick" Handler="listBoxItem_DoubleClick"/>
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>

アイコンが出るようになった。

別スレッドでアイコン画像の読み込みをする

        public DirectoryInfo Current
        {
            get { return current_; }
            set
            {
                current_ = value;
                NotifyPropertyChanged("Current");
                NotifyPropertyChanged("Path");
                files_.Clear();
                var workList=new List<Item>();
                try
                {
                    foreach (var e in current_.GetFileSystemInfos())
                    {
                        // FileSystemInfoだけのリストを作って、
                        // 後でアイコン画像をロードする
                        var item=new Item
                        {
                            Info = e
                        };
                        files_.Add(item);
                        workList.Add(item);
                    }

                    // 別スレッドでビットマップ更新を呼び出す
                    var task = new Task(() =>
                    {
                        foreach (var item in workList)
                        {
                            var source = LoadBitmapSource(item.Info);
                            source.Freeze(); // 重要
                            Action action = () =>
                            {
                                // UIスレッド
                                item.Bitmap = source;
                            };
                            dispatcher_.Invoke(action);
                        }
                    });
                    task.Start();
                }
                catch (UnauthorizedAccessException e)
                {
                    // do nothing
                }
                catch (DirectoryNotFoundException e)
                {
                    // do nothing
                }
            }
        }

github作った。
https://github.com/ousttrue/CSFiler