LoginSignup
0
5

More than 3 years have passed since last update.

Xamarin.Forms色々やってみた。

Last updated at Posted at 2019-12-11

Xamarin.Formsというのはiosとandroidの両方共通で使えるもの。

HelloWorld

Labelは文字列を表示する
HorizontalOptionsフィールドは横の位置を表し、VerticalOptionsフィールドは縦位置を表す。
Textフィールドは表示するテキストを表す。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App5.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

InitializeComponentでxaml側を描画している。

MainPage.xaml.cs
using System.ComponentModel;
using Xamarin.Forms;

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

実行結果

xamarin1.PNG

Binding

ちっとBindingは欲しいし、適当にやってみようか。ということでBindingできるか検証。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App5.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="{Binding Name}" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

WPFと同じようにINotifyPropertyChangedを実装して、登録を行う。
ただし、DataContextがないのでBindingContextというそれっぽいやつにBindingを行う。

MainPage.xaml.cs
using System.ComponentModel;
using Xamarin.Forms;

namespace App5
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        private MainVM MyVM = new MainVM();
        public MainPage()
        {
            InitializeComponent();
            BindingContext = MyVM;
        }
    }

    public class MainVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _Name = "HelloWorld";

        public string Name
        {
            get => _Name;
            set
            {
                _Name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }
    }
}

実行結果

xamarin2.PNG

Binding本当にできているのか?

表示時はできたが、はたして本当にできているのか不安なのでボタンをクリックしてViewModelを変更することによってxamlが変更されるかどうかを確かめる。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App5.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <StackLayout HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand"
            Orientation="Vertical">
            <Label Text="{Binding Name}" />
            <Button Text="ボタン" Clicked="Button_Clicked"></Button>
        </StackLayout>

    </StackLayout>
</ContentPage>
MainPage.xaml.cs
using System.ComponentModel;
using Xamarin.Forms;

namespace App5
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        private MainVM MyVM = new MainVM();
        public MainPage()
        {
            InitializeComponent();
            BindingContext = MyVM;
        }

        private void Button_Clicked(object sender, System.EventArgs e)
        {
            MyVM.Name = "HelloWorld2";
        }
    }

    public class MainVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _Name = "HelloWorld";

        public string Name
        {
            get => _Name;
            set
            {
                _Name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }
    }
}

ボタンをクリックしてHelloWorldがHelloWorld2になっていれば成功。

実行結果
xamarin3.PNG
きちんとなっている。

ListView

stringのリストを表示

ItemSourceにリストを入れる。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App4.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <ListView ItemsSource="{Binding Fruits}">
        </ListView>
    </StackLayout>
</ContentPage>

VMクラスにリストを入れる。

MainPage.xaml.cs
public class MainVM:INotifyPropertyChanged
{
    private ObservableCollection<string> _Fruits = new ObservableCollection<string>()
    {
        "apple",
        "banana",
        "cherry",
        "drian"
    };

    public ObservableCollection<string> Fruits
    {
        get => _Fruits;
        set
        {
            _Fruits = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Fruits)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

実行結果
xamarin1.PNG

Converterを使ってクラスで特定のフィールドを表示
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:App4"
             mc:Ignorable="d"
             x:Class="App4.MainPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:FruitToStringConverter x:Key="FruitToStringConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <ListView ItemsSource="{Binding Fruits, Mode=OneWay, Converter={StaticResource FruitToStringConverter}}">
        </ListView>
    </StackLayout>
</ContentPage>

コンバータークラスを作成
Convertはソースからxaml側へ
ConvertBackはxamlからソース側へ。
ConvertBackは今回使わないのでExceptionで残しておく。

MainPage.xaml.cs
public class FruitToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var json = JsonConvert.SerializeObject(value);
        return JsonConvert.DeserializeObject<List<Fruit>>(json).Select(x => x.Name);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new Exception("エラーです。");
    }
}

実行結果は上のstringのリスト表示と同じ。

ViewCellを使ってクラスの複数フィールドを表示

ViewCell直下ではListの中のクラスのFruitのフィールド名をBindingできる。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:App4"
             mc:Ignorable="d"
             x:Class="App4.MainPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:FruitToStringConverter x:Key="FruitToStringConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <ListView ItemsSource="{Binding Fruits, Mode=OneWay}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell Height="150">
                        <StackLayout Orientation="Horizontal">
                            <Label Text="{Binding Id}"></Label>
                            <Label Text="{Binding Name}"></Label>
                            <Label Text="{Binding Price}"></Label>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

VMクラス再掲

MainPage.xaml.cs
public class MainVM:INotifyPropertyChanged
{
    private ObservableCollection<Fruit> _Fruits = new ObservableCollection<Fruit>()
    {
        new Fruit(){Id = 1, Name = "apple", Number = 6, Price = 180},
        new Fruit(){Id = 2, Name = "banana", Number = 7, Price = 220},
        new Fruit(){Id = 3, Name = "cherry", Number = 5, Price = 210}
    };

    public ObservableCollection<Fruit> Fruits
    {
        get => _Fruits;
        set
        {
            _Fruits = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Fruits)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

実行結果
xamarin2.PNG

ページ遷移

NavigationPageによる遷移

MainPageをNavigationPageに変える。

App.xaml.cs
public App()
{
    InitializeComponent();

    MainPage = new NavigationPage(new MainPage());
}

MainPageの他に、Page1,Page2を作り遷移していく

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:App4"
             mc:Ignorable="d"
             x:Class="App4.MainPage">
    <StackLayout>
        <Button Text="Page1へ" Clicked="Button_Clicked"></Button>
    </StackLayout>
</ContentPage>

Navigation.PushAsync(Page, true)でPageに遷移する。第2引数はアニメーションのありなし。

MainPage.xaml.cs
public partial class MainPage : ContentPage
{
    private MainVM MyVM = new MainVM();

    public MainPage()
    {
        InitializeComponent();
        BindingContext = MyVM;
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        Navigation.PushAsync(new Page1(), true);
    }
}
Page1.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App4.Page1">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Button Text="Mainへ" Clicked="Button_Clicked"></Button>
            <Button Text="Page2へ" Clicked="Button_Clicked_1"></Button>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
Page1.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App4
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Page1 : ContentPage
    {
        public Page1()
        {
            InitializeComponent();
        }

        private void Button_Clicked(object sender, EventArgs e)
        {
            Navigation.PopToRootAsync();
        }

        private void Button_Clicked_1(object sender, EventArgs e)
        {
            Navigation.PushAsync(new Page2(), true);
        }
    }
}
Page2.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App4.Page2">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Button Text="Mainへ" Clicked="Button_Clicked"></Button>
            <Button Text="Page1へ" Clicked="Button_Clicked_1"></Button>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
Page2.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App4
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Page2 : ContentPage
    {
        public Page2()
        {
            InitializeComponent();
        }

        private void Button_Clicked(object sender, EventArgs e)
        {
            Navigation.PopToRootAsync();
        }

        private void Button_Clicked_1(object sender, EventArgs e)
        {
            Navigation.PushAsync(new Page1(), true);
        }
    }
}

実行結果
xamarin3.PNG

上の青いところが出てしまう。

Android実機デバッグ

以下の記事が参考になる。
https://tech-blog.cloud-config.jp/2017-06-06-execute-xamarin-helloworld-with-android-device/

0
5
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
5