はじめに
タイトルだけ見ると、ググっておしまいな気がするけど
半日くらい溶かしたので、備忘録として残しておく
ちなみにググってたくさん出てくる「ビルドアクションをリソースに」すれば治る症状とは別のお話
結論
MVVMに則ってView
とViewModel
にコードを分けている
<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に画像のパスを割り当てる
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にはならない
実際の動き
ボタンクリックすることで表示されている画像が切り替わる
詳細
結論が長くなった。ここから詳細の説明
プロジェクトを立ち上げます
.NET 6のWPFアプリケーションをつくり
適当に画像を2枚用意して、ReactiveProperty
をインストールする
脱線
おめでとうございます
画像を2枚用意する
実行ファイルと同じ階層に画像を2枚用意する
View側のImage
にはサイズを与える
<Image Source="{Binding MyImage.Value}" Width="256" Height="256"/>
今回画像サイズは縦横256pxでつくっている
上記記事と違い、自分の環境ではStrech
にFill
やNone
を入れても、画像は表示された
おわりに
ViewModel
については特筆すべきことはないので、詳細おわり
繰り返しになるが、表示はされてもメモリ食い荒らしそうなコードで気持ちがわるい
ボタンクリック動作のたびにnew
を通る。。。
参考