みかづきメモ

学習したことのメモとか、日記とか、備忘録。

Xamarin.Forms の ToolBarItems で左に置く

Xamarin.Forms にて、 ContentPage などにある ToolBarItems
これはツールバーに対して、アイテムを追加できるプロパティなのですが、
右側からしか配置されません。

公式フォーラムなどでもよく議論されているネタみたいなのですが、
サポートされていないため、自分で実装する必要があります。

幸い、やり方はフォーラムや GitHub にてあったので、それを元にやってみようと思います。


既に上で貼ったページで指摘されている通り、 ToolBarItems で左に配置したい場合は、
ContentPage などをカスタマイズする必要があります。
今回の場合は、 ContentPage だけカスタマイズすればいいので、
GitHub にあるサンプルと、フォーラムのを参考に作っていきます。


ちなみに GitHub のサンプル:

カスタマイズする ContentPage の仕様としては、こんな感じで実装してみます。
それ以外は、通常の ContentPage と同じということで。

iOS 側の実装

まずは、 iOS 側での実装です。
こちらは、フォーラムにも解決方法として、コードが載せてあります。

[assembly: ExportRenderer(typeof(ContentPage), typeof(NavigationPageRenderer))]

namespace Hoge
{
    public class NavigationPageRenderer : PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            var bindItems = (this.Element as ContentPage).ToolbarItems.OrderBy(w => w.Priority);
            var items = this.NavigationController.TopViewController.NavigationItem;
            var rightItems = new List<UIBarButtonItem>();
            var leftItems = items.LeftBarButtonItems?.ToList() ?? new List<UIBarButtonItem>();
            foreach (var item in bindItems)
            {
                if (item.Priority < 0)
                {
                    leftItems.Add(item.ToUIBarButtonItem());
                }
                else
                {
                    rightItems.Add(item.ToUIBarButtonItem());
                }
            }

            items.SetRightBarButtonItems(rightItems.ToArray(), animated);
            items.SetLeftBarButtonItems(leftItems.ToArray(), animated);
        }
    }
}

items.RightBarButtonItems には、 XAML で指定した ToolbarItem がすでに入っているので、
使わずに、新たに作りなおす方向で(これでいいのかはわからないけども)。

XAML

次に、 XAML から使います。
これは、 Shared だったり PCL だったりのプロジェクトでも大丈夫です。

<ContentPage x:Class="Hoge.SamplePage"
     xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
     Title="{Binding NavigationTitle}"
     mvvm:ViewModelLocator.AutowireViewModel="True">
    <ContentPage.ToolbarItems>
        <ToolbarItem Command="{Binding HelloCommand, Mode=OneWay}"
             Text="Hello" Priority="-1" />
        <ToolBarItem Command="{Binding GoodCommand, Mode=OneWay}"
             Text="Good" Priority="1" />
    </ContentPage.ToolbarItems>
    <Label HorizontalOptions="Center" Text="Hello"
        VerticalOptions="Center" />
</ContentPage>

ViewModel は適当に…

とりあえず、これで動きます。
若干違うけどこんなかんじ: f:id:MikazukiFuyuno:20151213235113p:plain

ということで。