放浪軍師のXamarin.Formsによるアプリ開発。
今回は画像表示についてです。
まず、初めて訪問された方は以下をお読みください。
画像を表示したい
そのまんまなんですけど、アプリに画像を表示するってのは当然ながら頻発しますので記録しておこうと思います。
ま、いうても画像表示だけだし楽勝だろと思ってたんですが、結構苦戦しました。いつもの事とか言うな
Imageコントロールを使う
画像はImageコントロールを使います。画像はPCLに置いてビルドアクションを埋め込みリリースにして、Sourceプロパティにパスを描いてやればそれだけで画像は表示する。そう思っていた頃が俺にもありました…。
※↓は画像表示されません。
<Image Source="ImageTest.Images.kasumi.jpg"/>
ちょっとこれが判らなくて色々調べてたんですが、以下matatabi_uxさんの記事によると特殊な書き方が必要だとの事。
matatabi-ux.hateblo.jp
…で、恐縮ですがこちらのImageSourceConverterをそのままお借りしてやってみると動きました。
[View]
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ImageTest.Views.MainPage" xmlns:cv="clr-namespace:ImageTest.Converters;assembly=ImageTest" Title="画像表示"> <ContentPage.Resources> <ResourceDictionary> <cv:ImageSourceConverter x:Key="ImageSourceConverter"/> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Button Text="華澄さん" Command="{Binding ImageChangeButton}" CommandParameter="ImageTest.Images.kasumi.jpg" /> <Button Text="メイさま" Command="{Binding ImageChangeButton}" CommandParameter="ImageTest.Images.mei.jpg" /> <Button Text="ストーカー" Command="{Binding ImageChangeButton}" CommandParameter="ImageTest.Images.miharu.jpg" /> <Image Source="{Binding ImageUri.Value, Converter={StaticResource ImageSourceConverter}}" /> </StackLayout> </ContentPage>
ポイントは
<Image Source="{Binding ImageUri.Value, Converter={StaticResource ImageSourceConverter}}" />
の部分で、Converterという知らない技術が使われています。
docs.microsoft.com
どうやらプロパティを変更する際に型変換を行う事ができるみたいですが、残念ながらまだ俺の知識では理解できません。ま、とりあえずそんなことができるんだ~程度で突き進みます。なーに本当に必要になったら嫌でも覚えるさ~(いつもの事)。
また、各ButtonのCommandParameterに画像のパスを入力しています。画面遷移の回で使ったReactiveCommand< T >と同じ使い方ですね。
www.gunshi.info
[ViewModel]
using Prism.Navigation; using Reactive.Bindings; using System; namespace ImageTest.ViewModels { public class MainPageViewModel : ViewModelBase { public ReactiveProperty<string> ImageUri { get; set; } = new ReactiveProperty<string>(); public ReactiveCommand<string> ImageChangeButton { get; } = new ReactiveCommand<string>(); public MainPageViewModel(INavigationService navigationService) : base(navigationService) { ImageChangeButton.Subscribe(x => ImageUri.Value = x); } } }
こちらも画面遷移の時と同じような感じです。ボタンをいくつ追加してもこの記述だけで済むのは素晴らしい!あ、ちなみになんですが、画面遷移の回で
標準版やPrism単体での画面遷移解説サイトはそこそこ見かけたんですが、そこにReactiveCommand< T >を組み合わせたこの形は、俺のブログには珍しくオリジナルの記述法になります多分。
なんて書いてたんですが…
Project BlueMonkeyでも同じことしてますねー。確か、Prismの開発してるブライアンさんがCommandParameterでナビゲーションのパスを渡してやるってのをしてたりしました。最近はロジック挟まないときはXAMLだけで出来る機能とかも追加されてたりします。https://t.co/LfNE1wncuk
— かずき@MHW が好き (@okazuki) 2018年8月29日
全然オリジナルじゃなかった!恥ずかC!恥ずかし乙女!!で、でもまぁPrismの開発者がやってるんなら間違いないから安心ですよね!ガンガン使っていきましょ。
閑話休題。
さて、これで動く!っと思ったが…実はこれUWPではボタンを押した瞬間にエラーが発生してしまいました。なんでじゃー!とまた色々調べていたら、このような記事が見つかりました。ShunsukeKawaiさんの記事ですね。
shunsukekawai.hatenablog.com
画像のパスを設定する際にAssemblyを引数に加えてやると表示されるようになりました。
という事で、さきのImageSourceConverterと組み合わせると
using System; using System.Reflection; using Xamarin.Forms; namespace ImageTest.Converters { public class ImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!(value is string)) { return default(ImageSource); } //以下だとUWPでエラーになる。 //return ImageSource.FromResource(value.ToString()); var assembly = typeof(App).GetTypeInfo().Assembly; return ImageSource.FromResource(value.ToString(), assembly); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
これでUWPでも無事動くようになりました。めでたしめでたしです。