XAMLを使わないWPF入門20「ListView + GridViewでヘッダー付き表示 + アイコン + 複数項目」

コンピュータ

リストビューでアイコンと複数項目を表示するサンプルプログラム

image

ファイル名:NoXAML20ListViewIcon.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:App.cs


using System;
using System.Windows;

namespace NoXAML20ListViewIcon;

public class App : Application
{
    [STAThread]
    public static void Main(string[] args)
    {
        var app = new App();
        app.Run();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var win = new FontIconImageListView();
        win.Show();
    }
}

ファイル名:AssemblyInfo.cs


using System.Windows;

[assembly:ThemeInfo(
    ResourceDictionaryLocation.None,            //where theme specific resource dictionaries are located
                                                //(used if a resource is not found in the page,
                                                // or application resource dictionaries)
    ResourceDictionaryLocation.SourceAssembly   //where the generic resource dictionary is located
                                                //(used if a resource is not found in the page,
                                                // app, or any theme specific resource dictionaries)
)]

ファイル名:MainWindow.cs


using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

public class FontIconImageListView : Window
{
    public FontIconImageListView()
    {
        Title = "フォントアイコン → 画像 ListView";
        Width = 500;
        Height = 300;

        var listView = new ListView();
        var gridView = new GridView();
        listView.View = gridView;

        // 名前列テンプレート(画像 + テキスト)
        var template = new DataTemplate(typeof(ItemData));

        var panelFactory = new FrameworkElementFactory(typeof(StackPanel));
        panelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

        var imageFactory = new FrameworkElementFactory(typeof(Image));
        imageFactory.SetValue(Image.WidthProperty, 16.0);
        imageFactory.SetValue(Image.HeightProperty, 16.0);
        imageFactory.SetValue(Image.MarginProperty, new Thickness(2));
        imageFactory.SetBinding(Image.SourceProperty, new System.Windows.Data.Binding("IconImage"));
        panelFactory.AppendChild(imageFactory);

        var textFactory = new FrameworkElementFactory(typeof(TextBlock));
        textFactory.SetValue(TextBlock.MarginProperty, new Thickness(4, 0, 0, 0));
        textFactory.SetBinding(TextBlock.TextProperty, new System.Windows.Data.Binding("Name"));
        panelFactory.AppendChild(textFactory);

        template.VisualTree = panelFactory;

        // 名前列
        gridView.Columns.Add(new GridViewColumn
        {
            Header = "名前",
            Width = 300,
            CellTemplate = template
        });

        // サイズ列
        gridView.Columns.Add(new GridViewColumn
        {
            Header = "サイズ",
            Width = 100,
            DisplayMemberBinding = new System.Windows.Data.Binding("DisplaySize")
        });

        // サンプルデータ
        listView.ItemsSource = new List<ItemData>
        {
            new ItemData("フォルダ1", true, 0),
            new ItemData("メモ.txt", false, 1234),
            new ItemData("フォルダ2", true, 0),
            new ItemData("動画.mp4", false, 987654321)
        };

        Content = listView;
    }

    public class ItemData
    {
        public string Name { get; }
        public bool IsDirectory { get; }
        public long Size { get; }

        public string DisplaySize => IsDirectory ? "—" : $"{Size:N0} B";

        public ImageSource IconImage { get; }

        public ItemData(string name, bool isDirectory, long size)
        {
            Name = name;
            IsDirectory = isDirectory;
            Size = size;

            var glyph = isDirectory ? "\uE8B7" : "\uE8A5"; // フォルダ or ファイル
            IconImage = CreateFontIconImage(glyph, 16, Brushes.Black);
        }

        private static ImageSource CreateFontIconImage(string glyph, double size, Brush brush)
        {
            var typeface = new Typeface(new FontFamily("Segoe MDL2 Assets"),
                                        FontStyles.Normal,
                                        FontWeights.Normal,
                                        FontStretches.Normal);

            var ft = new FormattedText(
                glyph,
                System.Globalization.CultureInfo.InvariantCulture,
                FlowDirection.LeftToRight,
                typeface,
                size,
                brush,
                VisualTreeHelper.GetDpi(Application.Current.MainWindow ?? new Window()).PixelsPerDip);

            var visual = new DrawingVisual();
            using (var dc = visual.RenderOpen())
            {
                dc.DrawText(ft, new Point(0, 0));
            }

            var bmp = new RenderTargetBitmap((int)Math.Ceiling(ft.Width), (int)Math.Ceiling(ft.Height), 96, 96, PixelFormats.Pbgra32);
            bmp.Render(visual);
            return bmp;
        }
    }
}

コメント