WPFで画像表示の実装

今回はC#でWPFアプリケーションの制作にポンコツ2人組が挑戦してみました。 開発環境はVisualStudio2019で、ライブラリはNewtonsoft.Jsonを使用しています。 APIから画像ファイル名のリスト(image1.jpgとimage2.jpg)を取得し、1件ずつAPIからダウンロードしてローカルに保存します。 その後で、ローカルに保存した画像ファイルを画面に出力します。 C#初心者が制作したものなのでいろいろとおかしい部分が多いと思います。プログラムを流用する際は適宜修正してください。

※この記事は2023/09/01時点の情報です。

MainWindow.xaml
APIから取得した画像を表示するためのScrollViewerとStackPanelを配置しています。

<Window x:Class="WpfApp3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ScrollViewer>
            <StackPanel x:Name="imageStackPanel" Orientation="Vertical" />
        </ScrollViewer>
    </Grid>
</Window>

MainWindow.xaml.cs
まず、APIから画像ファイル名のリストを取得します。 取得したリストをループして画像ファイルの実体をAPIから取得し、 ローカルの指定フォルダ(今回はE:\\VisualStudioProject\Images)に保存します。 最後に保存した画像ファイルを画面に表示させています。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Newtonsoft.Json;

namespace WpfApp3
{
    public partial class MainWindow : Window
    {
        private const string ApiBaseUrl = "http://localhost:8080"; // APIのベースURL
        private const string DownloadedImagesPath = "E:\\VisualStudioProject\\Images";

        public MainWindow()
        {
            InitializeComponent();
            LoadAndDisplayImagesAsync();
        }

        private async void LoadAndDisplayImagesAsync()
        {
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    HttpResponseMessage response = await client.GetAsync(ApiBaseUrl + "/image-list");

                    if (response.IsSuccessStatusCode)
                    {
                        string responseBody = await response.Content.ReadAsStringAsync();
                        List<string> imageList = JsonConvert.DeserializeObject<List<string>>(responseBody);

                        foreach (string imageName in imageList)
                        {
                            await DownloadAndDisplayImageAsync(imageName);
                        }
                    }
                    else
                    {
                        MessageBox.Show("APIから画像リストの取得に失敗しました。");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("エラーが発生しました: " + ex.Message);
                }
            }
        }

        private async Task DownloadAndDisplayImageAsync(string imageName)
        {
            using (HttpClient client = new HttpClient())
            {
                HttpResponseMessage imageResponse = await client.GetAsync(ApiBaseUrl + "/images/" + imageName);

                if (imageResponse.IsSuccessStatusCode)
                {
                    byte[] imageBytes = await imageResponse.Content.ReadAsByteArrayAsync();
                    string imagePath = Path.Combine(DownloadedImagesPath, imageName);

                    Directory.CreateDirectory(DownloadedImagesPath);
                    File.WriteAllBytes(imagePath, imageBytes);

                    BitmapImage bitmapImage = new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute));

                    Image imageControl = new Image
                    {
                        Source = bitmapImage,
                        Stretch = System.Windows.Media.Stretch.Uniform,
                        Width = 150,
                        Height = 150,
                        Margin = new Thickness(5)
                    };

                    // 画像を表示するStackPanelに追加
                    imageStackPanel.Children.Add(imageControl);
                }
            }
        }
    }
}

ImageController.java
一応APIのソースも掲載しておきます。今回はSpring Bootで制作しています。 image1.jpgとimage2.jpgを用意してresources/staticに配置してください。

package com.example.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ImageController {

    @GetMapping(value = "/image-list", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<String>> getImageList() throws IOException {
        List<String> imageList = new ArrayList<>();
        imageList.add("image1.jpg");
        imageList.add("image2.jpg");
        // 他の画像ファイル名も追加
        
        return ResponseEntity.ok().body(imageList);
    }
    
    @GetMapping(value = "/images/{imageName:.+}", produces = MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<Resource> getImage(@PathVariable String imageName) throws IOException {
        Resource imageResource = new ClassPathResource("static/" + imageName);
        
        if (!imageResource.exists()) {
            return ResponseEntity.notFound().build();
        }

        InputStream imageStream = imageResource.getInputStream();
        return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(new InputStreamResource(imageStream));
    }

}

以下がアプリケーションを実行した画面です。上がimage1.jpg、下がimage2.jpgです。 何とかC#のWPFで画像を表示することができました。

C#のWPFでAPIからダウンロードした画像を表示

管理人情報