1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

XamarinのXAML基礎勉強メモ1

Posted at

Xamarin勉強メモ

仕事でXamarinを使用するので、勉強メモとして残しておく。

XAMLとは

Xamarin.Formsのページを作成するのに使われる。

まずはラベルのテキスト設定

<?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="HelloWorld.MyPage"
             Title="Hello world">
   <ContentPage.Content>
     <Label Text="Hello world" />  // ここでラベルを作成し、Textプロパティに値を設定している
   </ContentPage.Content>
</ContentPage>

上記の例の箇所は省略可能。

StackLayoutとボタンクリックイベント

StackLayoutは複数のコントロールを縦や横に並べるコントロールのこと。
LabelとButtonを配置すると以下のようになる。

<?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="HelloWorld.MyPage"
             Title="Hello world">
   <StackLayout>
     <Label Text="Hello world" />
     <Button Text="Click me" 
             Clicked="OnClicked" /> // クリックイベント
   </StackLayout>
</ContentPage>

次にイベントの設定方法
今回はボタンのクリックイベントをC#側に実装する例とする。

using System;
using Xamarin.Forms;
namespace HelloWorld
{
   public partial class MyPage : ContentPage
   {
     public MyPage()
      {
          InitializeComponent();
       }
 
       private void OnClicked(object sender, EventArgs args)
       {
         // ここに処理を書く
       }
    }
}

Grid

Gridコントロールは画面を縦横で分割して、そこにコントロールを配置できます。
行はRowDefinitionsプロパティで定義し、列はColumnDefinitionsプロパティで定義する。

//Gridのみを抜粋
<Grid> 
  // 行を3分割にしている
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>

  // 列を3分割にしている
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>

  // 1×1のグリッドに配置
  <Button Text="0,0" />

  // 2×2のグリッドに配置
  <Button Text="1,1"
          Grid.Row="1"
          Grid.Column="1" />
  // 3×3のグリッドに配置
  <Button Text="2,2"
          Grid.Row="2"
          Grid.Column="2" />
</Grid>

StaticResource 共通定義

StaticResourceの設定方法

<ContentPage.Resources>
   <ResourceDictionary>
     // x:Keyで設定した名前でアクセスできる
     <x:String x:Key="text">Hello world</x:String>
   </ResourceDictionary>
</ContentPage.Resources>

  // x:Keyで設定した名前でデータを取得
  <Label Text="{StaticResource text}"
         HorizontalOptions="Center"
         VerticalOptions="Center" />

C#側クラスのstaticメンバを呼び出す方法

namespace HelloWorld
{
  public static class StaticItem
  {
    public static string Message { get; } = "Hello static world";
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             // staticクラスのnamespaceを設定
             xmlns:local="clr-namespace:HelloWorld;assembly=HelloWorld"
             x:Class="HelloWorld.MyPage"
             Title="Hello world">

  // x:Stackで取得する
  <Label Text="{x:Static local:StaticItem.Message}"
         HorizontalOptions="Center"
         VerticalOptions="Center" />

データバインディング

データバインディングはソースとターゲットの間の同期をとるために使用される。

コントロール同士のデータバインディング

 <StackLayout VerticalOptions="Center">
   <Slider x:Name="slider"
           Maximum="100"
           Minimum="0"
           VerticalOptions="StartAndExpand" />
   // SliderコントロールのValueプロパティとLabelのTextプロパティを同期している
   <Label Text="{Binding Value, Source={x:Reference slider}}"
          HorizontalOptions="Center" />
 </StackLayout>

x:Referenceで名前付きのコントロールのインスタンスを取得できるので、それを使用してLabelのTextプロパティとSliderのValueプロパティを同期しています。

データバインディングにはModeプロパティがあり、データバインディングの同期方向をカスタマイズすることができる。

  • Default: バインドしているターゲットのプロパティに指定されたデフォルトの値が使用される。
  • OneWay: ソースからターゲットへの一方通行で同期される。
  • OneWayToSource: ターゲットからソースへの一方通行で同期される。
  • TwoWay: ソースとターゲットの双方向で同期される。

BindingContextについて

BindingContextはBindableObjectクラスに定義されているプロパティになる。
BindingContextに設定するオブジェクトはINotifyPropertyChangedインターフェースを実装する。
INotifyPropertyChangedのPropertyChangedイベントを監視して、データ変更の検知を行い、ターゲットの更新を行います。
まずは、INotifyPropertyChangedの実装定義をしておいて、それを継承していく方法を使います。

using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace HelloWorld
{
  public class BindableBase : INotifyPropertyChanged
  {
    protected BindableBase()
    {
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
      if (object.Equals(field, value)) { return false; }

      field = value;
      this.OnPropertyChanged(propertyName);
      return true;
    }
  }
}
namespace HelloWorld
{
  public class MyPageViewModel : BindableBase
  {
    private double sliderValue;
    public double SliderValue
    {
      get { return this.sliderValue; }
      set { this.SetProperty(ref this.sliderValue, value); this.OnPropertyChanged(nameof(LabelValue)); }
    }
 
    public string LabelValue => string.Format("This is slider value '{0:000}'", this.SliderValue);
 }
}
<?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:local="clr-namespace:HelloWorld"
             x:Class="HelloWorld.MyPage">
  <ContentPage.BindingContext>
    <local:MyPageViewModel />
  </ContentPage.BindingContext>
  <StackLayout VerticalOptions="Center">
    <Slider Maximum="100"
            Minimum="0"
            HorizontalOptions="Fill"
            Value="{Binding SliderValue}" />
    <Label Text="{Binding LabelValue}"
           HorizontalOptions="Fill" />
  </StackLayout>
</ContentPage>

コレクションのデータバインディング

ListViewというコントロールを使用してコレクションをバインディングすることが可能です。
コレクションのバインディングにはItemsSourceプロパティにコレクションをデータバインドすることで行います。
その際にコレクションの要素の増減に対応するにはINotifyCollectionChangedインターフェースを実装して、CollectionChangedイベントを発行する必要がある。
このような条件があるため、可変コレクションの場合はObservableCollectionというINotifyCollectionChangedインターフェースを実装する。
可変でない場合はIEnumerableインターフェースでもListでも問題ない。

namespace HelloWorld
{
  public class Person
  {
    public string Name { get; set; }
  }
}
using System;
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace HelloWorld
{
  public class MyPageViewModel : BindableBase
  {
    public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();
    public MyPageViewModel()
    {
      var r = new Random();
      Device.StartTimer(
        TimeSpan.FromSeconds(5),
        () =>
        {
          this.People.Add(new Person { Name = $"tanaka {r.Next()}" });
          return true;
        });
    }
  }
}
<?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:local="clr-namespace:HelloWorld"
             x:Class="HelloWorld.MyPage">
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness">
      <On Platform="iOS">0,20,0,0</On>
    </OnPlatform>
  </ContentPage.Padding>
  <ContentPage.BindingContext>
    <local:MyPageViewModel />
  </ContentPage.BindingContext>
  // ItemsSourceにPeopleクラスをバインディングして
  <ListView ItemsSource="{Binding People}">
    // ItemTemplateのDateTemplateを設定しPeopleクラスのNameプロパティをバインディングする
    <ListView.ItemTemplate>
      <DataTemplate>
        <TextCell Text="{Binding Name}" />
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

参考文献

Xamarin.Forms入門

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?