連載
» 2016年08月31日 05時00分 UPDATE

.NET TIPS:Xamarin.Forms:プラットフォームに合わせた改行文字列を使うには?

Xamarin.Formsでは、プラットフォームごとに異なる改行文字列を統一的に扱うためにEnvironment.NewLineプロパティを利用できる。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

対象:Visual Studio 2015以降


 Xamarin.Formsは、XAMLとC#を使ってAndroid/iOS/Windows向けのクロスプラットフォーム開発を行える開発環境だ。

 文字列を扱う場合には、プラットフォームによって異なる改行文字列が問題になる。どのようにしたら、プラットフォームに適切な改行文字列を得られるだろうか? また、画面の表示、例えばLabelコントロールに表示する文字列を改行するにはどうしたらよいだろうか? 本稿ではこれらの方法について解説する。

プラットフォームに合わせた改行文字列を取得するには?

 C#のコードで改行文字列を取得するには、Environmentクラス(System名前空間)のNewLineプロパティを参照すればよい(次のコード)。iOSとAndroidでは「\n」(=0x0A)が、Windowsでは「\r\n」(=0x0D 0x0A)という改行文字列が得られる。

string cr = System.Environment.NewLine;

プラットフォームに合わせた改行文字列を取得する(C#)
文字列変数「cr」には、iOSとAndroidでは「\n」(=0x0A)が、Windowsでは「\r\n」(=0x0D 0x0A)が入る。

画面上で改行するには?

 LabelコントロールやButtonコントロール(ともにXamarin.Forms名前空間)などに表示する文字列を改行するにはどうしたらよいだろうか?

 コードビハインドから文字列をセットする場合は、前述したEnvironment.NewLineプロパティを改行したい位置に挿入すればよい。あるいは、文字列中に「\n」(=0x0A)を記述してもよい(Windowsであっても)。

 ではXAMLではどう書けばよいだろうか? WPFやUWPのTextBlockコントロールでは<LineBreak>要素を使って改行していたが、Xamarin.FormsのLabelコントロールなどにはそれがない。代わりに、次のコードのようにTextプロパティ中の改行がそのまま画面に反映されるようになっている。

<Label >
  <Label.Text>
&lt;Label.Text&gt;中の
文字列で改行
  </Label.Text>
</Label>

Labelコントロールの文字列を改行する例(XAML)
Xamarin.Formsでは、Textプロパティに記述した文字列内の改行が画面に反映される。
改行した次の行の先頭に空白を置くと、それも画面に反映されてしまうので注意しよう。この例では、「文字列で改行」の左側に空白を挿入すると、画面上にもその空白が表示される。その空白の分だけ、「文字列で改行」の文字が右にずれてしまうのだ。

XAMLコードでEnvironment.NewLineを指定するには?

 画面上で改行するには、上記のようにTextプロパティ中で改行するのが簡単だ。ただし、Visual Studioの自動フォーマット機能などによって改行後の行頭に空白が挿入されることがある。改行後の空白は画面に反映されるため、思わぬバグになりかねない。

 そのようなトラブルを避けるには、XAMLコードできちんとEnvironment.NewLineを記述してやればよい。

 それにはまず、System名前空間を参照できるようにXML名前空間を定義する(次のコード)。

<?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:dotNetTips1156"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             x:Class="dotNetTips1156.MainPage">

System名前空間を参照できるようにXML名前空間を定義する例(XAML)
画面を定義しているXAMLファイルの先頭部分。太字の部分を追加した。

 そうしたら、例えばLabelコントロールを次のコードのように記述する。「x:Static」マークアップ拡張を使ってEnvironment.NewLineプロパティをFormattedTextプロパティに配置するのだ。このとき、通常の文字列と「x:Static」マークアップ拡張は混在できないので、<Span>要素を使って分ける必要がある。

 なお、Xamarin.Formsの「x:Static」マークアップ拡張は、WPFのものと同様である。

<Label>
  <Label.FormattedText>
    <FormattedString>
      <Span Text="XAML中で" />
      <Span Text="{x:Static sys:Environment.NewLine}" />
      <Span Text="Environment.NewLineを使用" />
    </FormattedString>
  </Label.FormattedText>
</Label>

「x:Static」マークアップ拡張を使ってEnvironment.NewLineを指定する例(XAML)
<Span>要素を利用する。ただし、<Span>要素はTextプロパティ内に配置できない。この例のように、FormattedTextプロパティに置かねばならない。

実際の例

 実際の例として、以上で説明したコードを試してみよう。

 ソリューションを新しく作るときに[Blank Xaml App (Xamarin.Forms Portable)]を選ぶ。そのPCLプロジェクトにある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:local="clr-namespace:dotNetTips1156"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             x:Class="dotNetTips1156.MainPage">
  <!--<Label Text="Welcome to Xamarin Forms!"
           VerticalOptions="Center" HorizontalOptions="Center" />-->
  <ContentPage.Resources>
    <ResourceDictionary>
      <OnPlatform x:TypeArguments="Font" x:Key="LabelFontSize"
                  Android="Large" iOS="Medium" WinPhone="Small"  />
      <Style TargetType="Label">
        <Setter Property="Font" Value="{StaticResource LabelFontSize}" />
      </Style>
    </ResourceDictionary>
  </ContentPage.Resources>
  <StackLayout VerticalOptions="Center" HorizontalOptions="Center" Spacing="10">
    <Label x:Name="Label0" />
    <Label x:Name="Label1" />

    <Label >
      <Label.Text>
【2】&lt;Label.Text&gt;中の
文字列で改行
      </Label.Text>
    </Label>

    <Label>
      <Label.FormattedText>
        <FormattedString>
          <Span Text="【3】XAML中で" />
          <Span Text="{x:Static sys:Environment.NewLine}" />
          <Span Text="Environment.NewLineを使用" />
        </FormattedString>
      </Label.FormattedText>
    </Label>

    <Button>
      <Button.Text>
【4】ボタンの文字列を
改行する
      </Button.Text>
    </Button>

  </StackLayout>
</ContentPage>

改行文字列と画面上で改行するサンプルコード(XAML)
自動生成されたLabelコントロールをコメントアウトし、<ContentPage.Resources>要素以降を追加した。また、先頭の<ContentPage>タグには、XML名前空間の定義(プレフィックス「sys」)を追加した。
Labelコントロールのうち、「Label0」と「Label1」には、後ほどコードビハインドから文字列を設定する。

 次に、コードビハインドのMainPage.xaml.csファイルに次のようなコードを追加して、「Label0」と「Label1」に文字列を設定する。

public MainPage()
{
  InitializeComponent();

  // 改行文字列を取得する
  string cr = System.Environment.NewLine;

  // 取得した改行文字列の文字コードをLabel0に表示
  var crCode = $"0x{(int)cr[0]:X2}";
  for (int i = 1; i < cr.Length; i++)
    crCode += $" 0x{(int)cr[i]:X2}";
  Label0.Text = $"Environment.NewLine = {crCode}";

  // 取得した改行文字列を使って、Label1の表示を改行する
  // また、文字列中に「\n」を書いても改行できる
  Label1.Text
    = $"【1】コードビハインドで{cr}Environment.NewLineを使用"
      + "\n画面表示には「\\n」(=0x0A)でもよい";
}

改行文字列の取得と画面上で改行するサンプルコード(C#)
MainPage.xaml.csファイルのコンストラクタに、太字の部分を追加した。

 これで実行してみると、次の画像のようになる。

Visual Studio Emulator for Androidでの実行結果
iOS Simulator for Windowsでの実行結果
Mobile Emulator(Windows 10)での実行結果 実行結果
上はVisual Studio Emulator for Androidでの実行結果。中はiOS Simulator for Windowsでの実行結果。下はMobile Emulator(Windows 10)での実行結果。なお、iOS Simulator for Windowsは本稿執筆段階でプレビュー段階となっている。使用方法については「XamarinアプリのMacでのビルドとiOS Simulator for Windows」を参照されたい。
Environment.NewLineで取得した改行文字列の文字コードを一番上のラベルに表示している。WindowsとiOS/Androidでは確かに違うと分かる。

まとめ

 プラットフォームに合わせた改行文字列をC#で取得するには、Environment.NewLineプロパティを使う。

 画面上で改行するには、XAMLコード内で改行すれば簡単だ。ただし、改行後の空白は画面に反映されてしまうので、無用なトラブルを避けるにはXAMLコードでEnvironment.NewLineプロパティを記述する。

「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。