放浪軍師のXamarin.Formsアプリ開発局

Xamarin.Forms+Prism+ReactivePropertyで素人がAndroidやUWPのアプリを右往左往しながら開発している様を発信していきます。性質上間違いも多いのでご注意ください。

画像を表示したい。ただそれだけだが苦戦した。

放浪軍師のXamarin.Formsによるアプリ開発
今回は画像表示についてです。
まず、初めて訪問された方は以下をお読みください。

www.gunshi.info

画像を表示したい

そのまんまなんですけど、アプリに画像を表示するってのは当然ながら頻発しますので記録しておこうと思います。
ま、いうても画像表示だけだし楽勝だろと思ってたんですが、結構苦戦しました。いつもの事とか言うな

Imageコントロールを使う

画像はImageコントロールを使います。画像はPCLに置いてビルドアクションを埋め込みリリースにして、Sourceプロパティにパスを描いてやればそれだけで画像は表示する。そう思っていた頃が俺にもありました…。
f:id:roamschemer:20180904020454p:plain
※↓は画像表示されません。

<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 >を組み合わせたこの形は、俺のブログには珍しくオリジナルの記述法になります多分

なんて書いてたんですが…


全然オリジナルじゃなかった!恥ずか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でも無事動くようになりました。めでたしめでたしです。

動作

無事に動くのが確認できました。iOSは確認できてないが…ま、大丈夫っしょ(適当)
[Android]
f:id:roamschemer:20180904025423g:plain:w150
[UWP]
f:id:roamschemer:20180904030025g:plain:w150

しっかし、あんとき書いたときメモの絵…、大活躍やね…