Realm Databaseを使用してCRUDアプリを作成(前編)

Realm Databaseを使ってCRUDを実装したシンプルなXamarin.Formsアプリを作ってみます。今回は前編としてCRUDのデータの作成(CREATE)と表示(READ)に該当する部分を作成します。データの表示にはComponentOne Studio for Xamarin(以下、C1 Xamarin)のFlexGridを使用します。

Realm Databaseとは?

Realm DatabaseはSQLiteと同じくローカルデータベースです。このデータベースは近年モバイルアプリをはじめてとして様々なアプリケーションで採用が進んでいます。Realm Databaseを使うメリットについてはオープンソースクロスプラットフォームである、SQLiteより処理が高速である、使い始めるのが簡単など色々と挙げられます。詳細については公式サイトをご覧ください。

realm.io

以下に作成手順を解説します。

Visual Studio 2017でXamarin.Forms (PCL)アプリを作成

まずはいつもどおりXamarin.Forms (PCL)アプリを作成します。現時点で最新のC1 Xamarin(2.3.20172.190)を使用するので各プロジェクトで使用するXamarin.Formsのバージョンを2.3.4.270に設定します。 f:id:ComponentOne_JP:20171114174823p:plain

Realm Databaseのインストール

Nuget パッケージ マネージャーから「Realm」を各プロジェクトにインストールします。 Realmはバージョン1.6をインストールします。 f:id:ComponentOne_JP:20171114180304p:plain

これに合わせてFodyは2.0.6、Newtonsoft.Jsonは9.0.1をインストールします。 f:id:ComponentOne_JP:20171115151149p:plain

f:id:ComponentOne_JP:20171115151209p:plain

また、Realmをインストールすると、各プロジェクトにFodyWeavers.xmlというファイルが作成されますが、UWPには作成されません。他のプロジェクトからコピーしておきます。

f:id:ComponentOne_JP:20171115152035p:plain

C1 Xamarin FlexGridのインストール

Nuget パッケージ マネージャーから「C1 Xamarin FlexGrid」を各プロジェクトにインストールします。 f:id:ComponentOne_JP:20171115152827p:plain

モデルの作成

データモデルを追加します。

public class DataModel : RealmObject
{
[PrimaryKey]
public int Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public float Height { get; set; }
public float Weight { get; set; }
}
ビューとビューモデルの作成(CREATE)

Realm Databaseにデータを入力するビューとビューモデルを作成します。 ビューのページにはデータを入力する Entry コントロールとRealm DatabaseへのCREATEを実行するボタンを配置します。

<?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="RealmDatabase.View.CreateData">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 0" Android="10, 20, 10, 0" WinPhone="10, 20, 10, 0" />
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="氏名(姓)"></Label>
<Entry Grid.Column="1" Grid.Row="0" x:Name="lastname" Text="{Binding LastName}"></Entry>
<Label Grid.Column="0" Grid.Row="1" Text="氏名(名)"></Label>
<Entry Grid.Column="1" Grid.Row="1" x:Name="firstname" Text="{Binding FirstName}"></Entry>
<Label Grid.Column="0" Grid.Row="2" Text="身長"></Label>
<Entry Grid.Column="1" Grid.Row="2" x:Name="height" Text="{Binding Height}"></Entry>
<Label Grid.Column="0" Grid.Row="3" Text="体重"></Label>
<Entry Grid.Column="1" Grid.Row="3" x:Name="weight" Text="{Binding Weight}"></Entry>
</Grid>
<Button x:Name="writebtn" Text="入力したデータを登録" Command="{Binding WriteDataCommand}"></Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>

ビューのコードビハインドではバインディングコンテキストを設定します。

    public partial class CreateData : ContentPage
{
public CreateData()
{
InitializeComponent();
var createdatavm = new CreateDataViewModel();
BindingContext = createdatavm;
}
}

ビューモデルではWriteDataメソッドをWriteDataCommandコマンドで呼び出します。WriteDataメソッドでRealm Databaseに入力データを追加しています。

public class CreateDataViewModel : INotifyPropertyChanged
{
Realm realm = Realm.GetInstance();
private string lastname;
public string LastName
{
get { return lastname; }
set
{
lastname = value;
OnPropertyChanged("LastName");
}
}
private string firstname;
public string FirstName
{
get { return firstname; }
set
{
firstname = value;
OnPropertyChanged("FirstName");
}
}
private string height;
public string Height
{
get { return height; }
set
{
height = value;
OnPropertyChanged("Height");
}
}
private string weight;
public string Weight
{
get { return weight; }
set
{
weight = value;
OnPropertyChanged("Weight");
}
}
public ICommand WriteDataCommand { get; private set; }
public CreateDataViewModel()
{
WriteDataCommand = new Command(WriteData);
}
public void WriteData()
{
realm.Write(() =>
{
realm.Add(new DataModel()
{
Id = realm.All<DataModel>().Count() + 1,
LastName = LastName,
FirstName = FirstName,
Height = float.Parse(Height, System.Globalization.CultureInfo.InvariantCulture),
Weight = float.Parse(Weight, System.Globalization.CultureInfo.InvariantCulture)
});
});
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ビューとビューモデルの作成(READ)

Realm Databaseに作成したデータをFlexGridで表示するビューとビューモデルを作成します。 ビューのページにはFlexGrid コントロールを配置します。

<?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="RealmDatabase.View.ListData"
xmlns:c1="clr-namespace:C1.Xamarin.Forms.Grid;assembly=C1.Xamarin.Forms.Grid">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 0" Android="10, 20, 10, 0" WinPhone="10, 20, 10, 0" />
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout>
<Grid VerticalOptions="FillAndExpand">
<c1:FlexGrid x:Name="grid" AutoGenerateColumns="False">
<c1:FlexGrid.Columns>
<c1:GridColumn Header="氏名(姓)" Binding="LastName" />
<c1:GridColumn Header="氏名(名)" Binding="FirstName"/>
<c1:GridColumn Header="身長" Binding="Height" />
<c1:GridColumn Header="体重" Binding="Weight" />
</c1:FlexGrid.Columns>
</c1:FlexGrid>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>

ビューのコードビハインドではバインディングコンテキストを設定します。また、FlexGridのItemSourceにビューモデル内でRealm Databaseにあるデータのコレクションを設定したAllDataを設定します。

public partial class ListData : ContentPage
{
public ListData()
{
InitializeComponent();
var listdatavm = new ListDataViewModel();
BindingContext = listdatavm;
grid.ItemsSource = listdatavm.AllData;
grid.IsReadOnly = true;
}
}

ビューモデルではAllData にRealm Databaseにあるデータのコレクションを設定しています。

public class ListDataViewModel : INotifyPropertyChanged
{
Realm realm = Realm.GetInstance();
private ObservableCollection<DataModel> alldata;
public ObservableCollection<DataModel> AllData
{
get { return alldata; }
set
{
alldata = value;
}
}
public ListDataViewModel()
{
AllData = new ObservableCollection<DataModel>(realm.All<DataModel>());
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ビューとビューモデルの作成(トップページ)

最後に各ビューのページ(CreateDataとListData)に遷移するボタンを配置したトップページのビューとビューモデルを作成します。

<?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="RealmDatabase.View.MainPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 0" Android="10, 20, 10, 0" WinPhone="10, 20, 10, 0" />
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout Padding="10">
<Button Text="Realm Databaseに登録" Command="{Binding NavToCreateCommand}"/>
<Button Text="FlexGridで表示" Command="{Binding NavToListCommand}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

ビューのコードビハインドではバインディングコンテキストを設定します。

public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var mainvm = new MainViewModel();
BindingContext = mainvm;
}
}

ビューモデルには各ページへのナビゲーションをNavToCreateCommand、NavToListCommand コマンドで追加しています。

class MainViewModel
{
public ICommand NavToListCommand { get; private set; }
public ICommand NavToCreateCommand { get; private set; }
public MainViewModel()
{
NavToListCommand = new Command(async () => await App.Current.MainPage.Navigation.PushAsync(new ListData()));
NavToCreateCommand = new Command(async () => await App.Current.MainPage.Navigation.PushAsync(new CreateData()));
}
}
実行してみる

以上で作成完了です。アプリをビルドして実行してみます。

f:id:ComponentOne_JP:20171116160324p:plainf:id:ComponentOne_JP:20171116160335p:plainf:id:ComponentOne_JP:20171116160349p:plain
Android
f:id:ComponentOne_JP:20171116161533p:plainf:id:ComponentOne_JP:20171116161539p:plainf:id:ComponentOne_JP:20171116161547p:plain
iOS
f:id:ComponentOne_JP:20171116162256p:plainf:id:ComponentOne_JP:20171116162310p:plainf:id:ComponentOne_JP:20171116162330p:plain
UWP

今回はCRUDのCREATE、READを実装しました。今後はUPDATE、DELETEも追加して後編として記事にしたいと思います。


作成したサンプルはこちらで公開しています。C1 Xamarinのライセンスも含まれていますので、NuGetパッケージを復元すれば実行可能です *1

ダウンロード(zipファイル:271KB)


*1:NuGetパッケージを利用するには、GrapeCityのNuGetフィードソース( http://nuget.c1.grapecity.com/nuget/ )を、Visual Studioの環境に追加する必要があります。