Help us understand the problem. What is going on with this article?

【Xamarin】Microsoft謹製のクロスプラットフォーム開発を触って遊んでみた

More than 1 year has passed since last update.

ユニバーサルWindowsプラットフォームアプリケーション(UWP)という仕組みを、
前々から触ってみたいと思っていまして。
たまたまXamarinに関わるきっかけがあったので、触りがてら遊んでみました備忘録です。

1. プロジェクトの作成

開発環境

  • OS...Windows10
  • IDE...VisualStudio2019 Professional (他エディションでも問題なし)

VisualStudio Installerを使用して、[.NETによるモバイル開発]のインストールを行っておきます。
image.png

プロジェクトファイルの作成

VisualStudioを起動し、[テンプレートの検索(Alt+S)]欄に「xamarin」と入力します。
[モバイルアプリ(Xamarin.Forms)]を選択します。
image.png

適当なプロジェクト名を設定します。今回は「xamarin_sample」を設定しました。
image.png

VisualStudioによりxamarin_sampleプロジェクトの初期化が行われます。
完成後のイメージは以下の通り。
image.png

デバッグしてみる

初期状態でF5キーを押して実行すると、初期画面が起動しました。
マテリアルデザインちっくな、クロスプラットフォーム向けのデザインですね~。Macのアプリみたい。
image.png

image.png

適当なコードにブレークポイントを貼ってやれば、難なくデバッグも可能です。さすがVS!
image.png

2. カスタマイズ

デフォルトのままだとなんとなく個性がない‥。没個性社会のたまもの‥。
というところで、アプリケーション全体のテーマを変更したいと思います。

テーマ

XAMLを読んでいると、背景色が事前に定義されたリソースとバインドされているようです。
これは、テーマを変更すると一括でアプリケーションのデザインが変えられるのでは?
テーマの設定個所を探すと、ありました。
以下の通りXAMLを書き換え、テーマを変更します。

xamarin_sample.UWP/App.xaml
<Application
    x:Class="xamarin_sample.UWP.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:xamarin_sample.UWP"
    RequestedTheme="Dark"> <!-- LightからDarkに変更 -->

</Application>
xamarin_sample.UWP/MainPage.xaml
<forms:WindowsPage
    x:Class="xamarin_sample.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:forms="using:Xamarin.Forms.Platform.UWP"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:xamarin_sample.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <!-- 背景色にバインドされているブラシのカラーが、テーマに適したものに変更される -->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>
</forms:WindowsPage>

実行すると、テーマカラーがDarkテーマに変更になっている! イカしますね~。
image.png

3. MVVMモデルを利用した画面描画

ところで、XAMLを使用しているということは、MVVMモデル(ModelViewViewModel)で構築されているのでは?
ViewModelClassを探したところ、設定されているページがありました。
さっそくMVVMモデルを使用して画面上のコンテンツを変更してみます。

表示箇所設定

以下の[About]タブのアプリケーション名称を変更したいと思います。
image.png

[AboutPage]にバインドされている[AboutViewModel]の継承元である[BaseViewModel]に、AppNameプロパティを追加します。
最終的にはこのプロパティを画面上にバインドするイメージですね。

xamarin_sample
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

using Xamarin.Forms;

using xamarin_sample.Models;
using xamarin_sample.Services;

namespace xamarin_sample.ViewModels
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>() ?? new MockDataStore();

        // ☆ AppNameプロパティの定義を追加する。↓
        string appName = string.Empty;
        public string AppName
        {
            get { return appName; }
            set { SetProperty(ref appName, value); }
        }
        // ☆ AppNameプロパティの定義の追加 ここまで

        bool isBusy = false;
        public bool IsBusy
        {
            get { return isBusy; }
            set { SetProperty(ref isBusy, value); }
        }

        string title = string.Empty;
        public string Title
        {
            get { return title; }
            set { SetProperty(ref title, value); }
        }

        protected bool SetProperty<T>(ref T backingStore, T value,
            [CallerMemberName]string propertyName = "",
            Action onChanged = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingStore, value))
                return false;

            backingStore = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

続いて、[AboutPage]にバインドされている[AboutViewModel]のコンストラクタに、
AppNameプロパティの値を設定する記述を追加します。

xamarin_sample/AboutViewModel.cs
using System;
using System.Windows.Input;

using Xamarin.Forms;

namespace xamarin_sample.ViewModels
{
    public class AboutViewModel : BaseViewModel
    {
        public AboutViewModel()
        {
            Title = "About";

            // ☆ 画面上に表示するアプリケーション名を指定する。
            // ☆ AppNameプロパティの定義は継承元であるBaseViewModelに追加する。
            AppName = "アプリケーション名を入力します。"; 

            OpenWebCommand = new Command(() => Device.OpenUri(new Uri("https://xamarin.com/platform")));
        }

        public ICommand OpenWebCommand { get; }
    }
}

AboutPageViewModelのAppNameプロパティをアプリケーション名称にバインドするよう、XAMLを書き換えます。

xamarin_sample/AboutPage.xaml
<!-- 前略 -->
    <!-- コンテントページのバインディングコンテキストにAboutViewModelが設定されている。-->
    <ContentPage.BindingContext>
        <vm:AboutViewModel />
    </ContentPage.BindingContext>
    <!-- 中略 -->
                <Label FontSize="22">
                    <Label.FormattedText>
                        <FormattedString>
                            <FormattedString.Spans>
                                <!-- ☆ AppNameプロパティをバインドする。 -->
                                <!-- ☆ <Span Text="AppName" FontAttributes="Bold" FontSize="22" /> から以下の通り書き換え -->
                                <Span Text="{Binding AppName}" FontAttributes="Bold" FontSize="22" />
                                <Span Text=" " />
                                <Span Text="1.0" ForegroundColor="{StaticResource LightTextColor}" />
                            </FormattedString.Spans>
                        </FormattedString>
                    </Label.FormattedText>
                </Label>
    <!-- 後略 -->

すると、[About]欄のアプリケーション名称が設定した値で表示されるようになりました!
image.png

値の書き換え

今回は[About]ページでボタンをクリックしたときにアプリケーション名を変更するよう、コードを書き換えます。
ふつうあり得ないですけどね、アバウトページの情報がボタンクリックするたびに書き換わったらいやじゃないですか。ワイはいやです。
でも今回はその仕様で組んでみます。

xamarin_sample/AboutPage.xaml
                <Label FontSize="22">
                    <Label.FormattedText>
                        <FormattedString>
                            <FormattedString.Spans>
                                <Span Text="{Binding AppName}" FontAttributes="Bold" FontSize="22" />
                                <Span Text=" " />
                                <Span Text="1.0" ForegroundColor="{StaticResource LightTextColor}" />
                            </FormattedString.Spans>
                        </FormattedString>
                    </Label.FormattedText>
                </Label>
                <!-- ☆ 以下の1行を追加してボタンを定義する。-->
                <Button Text="アプリケーション名を設定する" Clicked="Button_Clicked" />

MVVMモデルの場合、画面上のオブジェクトを直接書き換えるのではなく、バインドされているViewModelを書き換えるお作法です。
お作法に乗っ取り、AboutPageにバインドされているViewModelを取得・値を書き換えるようにコードを編集します。

AboutPage.xaml.cs
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using xamarin_sample.ViewModels;

namespace xamarin_sample.Views
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class AboutPage : ContentPage
    {
        public AboutPage()
        {
            InitializeComponent();
        }

        // ☆ ボタンクリックイベントのハンドラ
        private void Button_Clicked(object sender, EventArgs e)
        {
            // 自身にバインドされているViewModelを取得する。
            var viewModel = BindingContext as AboutViewModel;

            // AppNameを書き換える。
            viewModel.AppName = "ザマリンサンプルアプリケーション";
        }
    }
}

すると、ボタンをクリックした時、ViewModelに設定された値を書き換えることで、バインドされている画面上のラベルも書き換わるクソプログラムが完成しました!
(GIF画像)
test.gif

4. まとめ

今回は簡単にですが、Xamarinのテンプレートプロジェクトを触ってみました。

最近は.NET Coreの対応やSQLServer on Linuxなど、Microsoftからクロスプラットフォーム向けのしくみが続々提供されていますね。
WPFの経験がある方であれば、UWPもかなり触りやすいのではないかな、と思います。

引き続きなにか一本プログラムを組んでみたいと思いますので、落ち着き次第報告させていただきます!

nqdior
C#メインのフルスタックエンジニア6年目。好きな技術は「高速化」。よろしくお願いしまーす。
https://github.com/nqdior
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした