0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WPFのViewにローカルの画像を表示する(MVVM)

Posted at

はじめに

タイトルだけ見ると、ググっておしまいな気がするけど
半日くらい溶かしたので、備忘録として残しておく

ちなみにググってたくさん出てくる「ビルドアクションをリソースに」すれば治る症状とは別のお話

結論

MVVMに則ってViewViewModelにコードを分けている

View
<Window>
<!-- Windowタグのプロパティは省略 -->
    <StackPanel>
        <Image Source="{Binding MyImage.Value}" Width="256" Height="256"/>
        <Button Command="{Binding ChangeImage}" Content="Change Image!!" />
    </StackPanel>
</Window>

MyImageをバインドして、.ValueにはBitmap型を割り当てる
そのビットマップのURIに画像のパスを割り当てる

ViewModel
internal class MainViewModel : INotifyPropertyChanged
{
   public ReactiveProperty<BitmapImage> MyImage { get; set; }
   public ReactiveCommand ChangeImage { get; }

   public MainViewModel()
   {
       string basePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
       Uri baseUri = new Uri(basePath);
       Uri imageUri = new Uri(baseUri, "./net6.0-windows/1.bmp");
       MyImage = new(new BitmapImage(imageUri));
       
       ChangeImage = new ReactiveCommand().WithSubscribe(() =>
       {
           var newImageUri = new Uri(baseUri, "./net6.0-windows/2.bmp");
           MyImage.Value = new(newImageUri);
       });
   }

   public event PropertyChangedEventHandler? PropertyChanged;
}

ハマったポイントとしては、画像を置いたパスが迷子になった点

実行ファイルが置いてあるところの画像を下記のように指定したが、画像が表示されず

動かないコード
Uri imageUri = new Uri("./1.bmp", UriKind.Relative);

結局丁寧にGetExecutingAssembly().Locationでパスを取得して
new Uri(baseUri, "./net6.0-windows/1.bmp");としてURIを結合した

Uriは書き換えできない

メモリを節約するために、単一のインスタンスのURIを書き換えようと思ったが
画像が表示されている最中はソースを書き換えることができず
仕方なく2つのビットマップをつかっている

_image.UriSource = null;
// nullにはならない

実際の動き

ボタンクリックすることで表示されている画像が切り替わる

Animation.gif

詳細

結論が長くなった。ここから詳細の説明

プロジェクトを立ち上げます

.NET 6のWPFアプリケーションをつくり
適当に画像を2枚用意して、ReactivePropertyをインストールする

脱線

おめでとうございます

画像を2枚用意する

実行ファイルと同じ階層に画像を2枚用意する

image.png

View側のImageにはサイズを与える

View
<Image Source="{Binding MyImage.Value}" Width="256" Height="256"/>

今回画像サイズは縦横256pxでつくっている
上記記事と違い、自分の環境ではStrechFillNoneを入れても、画像は表示された

おわりに

ViewModelについては特筆すべきことはないので、詳細おわり

繰り返しになるが、表示はされてもメモリ食い荒らしそうなコードで気持ちがわるい

ボタンクリック動作のたびにnewを通る。。。

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?