Xamarin.Forms에서 이벤트에 Command 바인딩

14748 단어 XamarinXamarin.Forms
Xamarin이 무상화되었기 때문에 여러 가지 시도하고 있습니다.
우선 UWP의 제작 앱을 Xamarin.Forms로 마이그레이션하려고 했는데, 처음부터 넘어졌기 때문에 그 때의 대응 방법을 남겨 둡니다.

UWP의 처리 내용



작성중인 UWP 앱은 Page의 Loaded 이벤트에 Command를 바인딩합니다.

UWP의 경우 xaml에 다음과 같이 작성하여 바인딩 할 수 있습니다 (아래 예제는 ReactiveProperty를 사용합니다. ReactiveProperty는 이 근처 참조).
<i:Interaction.Behaviors>
    <core:EventTriggerBehavior EventName="Loaded">
        <react:EventToReactiveCommand Command="{x:Bind ViewModel.LoadedCommand}"/>
    </core:EventTriggerBehavior>
</i:Interaction.Behaviors>

Xamarin.Forms에서의 대응 방법



Xamarin.Forms에서는 먼저 Page 클래스에 Loaded 이벤트가 없습니다. Appearing 이벤트가 거의 상당하는 이벤트와 같기 때문에 이 이벤트에 바인드 하는 것을 생각했습니다.

UWP와 마찬가지로 Behavior를 사용하여 바인딩하는 방법을 조사했습니다 (Xamarin.Forms.Behaviors
도서관이 있거나 하기 때문에 ,,)가 반나절 정도 조사해도 몰랐기 때문에 일단 포기하고 다른 방법을 검토했습니다.

검색한 결과, 첨부 프로퍼티를 작성하면 바인드 할 수 있을 것 같았기 때문에 작성해 확인했습니다.

첨부 속성 클래스



첨부 속성을 추가하기 위해 다음과 같은 클래스를 만들었습니다.

AttachedProp.cs
using System;
using System.Windows.Input;
using Xamarin.Forms;

namespace XFAttatchedPropSample.Views
{
    /// <summary>
    /// 添付プロパティクラス
    /// </summary>
    public class AttachedProp
    {
        /// <summary>
        /// Appearing コマンドプロパティ
        /// </summary>
        public static readonly BindableProperty AppearingCommandProperty =
            BindableProperty.CreateAttached(
                "AppearingCommand",                     // プロパティ名
                typeof(ICommand),                       // プロパティの型
                typeof(Page),                           // 添付対象の型
                null,
                BindingMode.OneWay,                     // デフォルト BindingMode
                null,
                OnAppearingCommandPropertyChanged,      // プロパティが変更された時に呼び出されるデリゲート
                null,
                null);

        /// <summary>
        /// Appearing コマンドプロパティの getter
        /// </summary>
        /// <param name="bindable">バインド対象オブジェクト</param>
        /// <returns>プロパティの値</returns>
        public static ICommand GetAppearingCommand(BindableObject bindable)
        {
            return (ICommand)bindable.GetValue(AttachedProp.AppearingCommandProperty);
        }

        /// <summary>
        /// Appearing コマンドプロパティの setter
        /// </summary>
        /// <param name="bindable">バインド対象オブジェクト</param>
        /// <param name="value">プロパティに設定する値</param>
        public static void SetAppearingCommand(BindableObject bindable, Command value)
        {
            bindable.SetValue(AttachedProp.AppearingCommandProperty, value);
        }

        /// <summary>
        /// Appearing コマンドプロパティ変更
        /// </summary>
        /// <param name="bindable">バインド対象オブジェクト</param>
        /// <param name="oldValue">変更前の値</param>
        /// <param name="newValue">変更後の値</param>
        public static void OnAppearingCommandPropertyChanged(BindableObject bindable, Object oldValue, Object newValue)
        {
            var page = bindable as Page;
            if (page == null)
            {
                return;
            }

            if (newValue != null)
            {
                page.Appearing += Page_Appearing;
            }
            else
            {
                page.Appearing -= Page_Appearing;
            }
        }

        /// <summary>
        /// Appearing イベント発生
        /// </summary>
        /// <param name="sender">送信元オブジェクト</param>
        /// <param name="e">イベント引数</param>
        private static void Page_Appearing(object sender, EventArgs e)
        {
            var command = GetAppearingCommand(sender as BindableObject);
            if (command != null)
            {
                if (command.CanExecute(e))
                {
                    command.Execute(e);
                }
            }
        }
    }
}

AppearingCommand라는 이름으로 ICommand 형식의 첨부 속성을 만들고 속성에 값이 설정되면 Appearing 이벤트에 대한 처리기를 등록합니다.
이벤트가 발생하면 속성에 설정된 Command를 호출합니다.

MainPage 및 MainPageViewModel



MainPage를 새로 만들고(Forms Xaml Page) 해당 ViewModel 클래스를 만듭니다.

바인드 하는 명령을 가지는 ViewModel 를 이하와 같이 작성했습니다.
명령이 실행된 것을 알 수 있도록(듯이), 실행되면(자) 메세지 캐릭터 라인 프로퍼티에 "Loaded"를 설정하도록 하고 있습니다.

명령과 속성은 ReactiveProperty를 사용하여 쉽게 만들 수 있으므로 ReactiveProperty를 사용합니다.

MainPageViewModel.cs
using Reactive.Bindings;
using System;

namespace XFAttatchedPropSample.ViewModels
{
    public class MainPageViewModel
    {
        public ReactiveProperty<String> Message { get; }

        public ReactiveCommand Loaded { get; }

        public MainPageViewModel()
        {
            Message = new ReactiveProperty<string>();

            Loaded = new ReactiveCommand();
            Loaded.Subscribe(_ =>
            {
                System.Diagnostics.Debug.WriteLine("Loaded");
                Message.Value = "Loaded";
            });
        }
    }
}

MainPage 측에서는 ContentPage 에 작성한 첨부 프로퍼티을 기술해 커멘드를 바인드 합니다.
         vw:AttachedProp.AppearingCommand="{Binding Loaded}"

명령이 실행되었음을 나타내는 메시지를 표시하기위한 Label도 배치하여 다음과 같이 작성했습니다.

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:vw="clr-namespace:XFAttatchedPropSample.Views;assembly=XFAttatchedPropSample"
             xmlns:vm="clr-namespace:XFAttatchedPropSample.ViewModels;assembly=XFAttatchedPropSample"
             x:Class="XFAttatchedPropSample.Views.MainPage"
             vw:AttachedProp.AppearingCommand="{Binding Loaded}"
             >

  <ContentPage.BindingContext>
    <vm:MainPageViewModel />
  </ContentPage.BindingContext>

  <Label Text="{Binding Message.Value}" FontSize="36" HorizontalOptions="Center" VerticalOptions="Center" />
</ContentPage>

마지막으로 App 클래스의 생성자를 만든 MainPage를 호출하도록 변경했습니다.
    public App()
    {
        MainPage = new Views.MainPage();
    }

실행 결과



작성한 앱을 실행하면 바인드한 명령이 호출되어 메시지가 설정되는 것을 확인할 수 있었습니다.

Android에서 실행 결과


UWP에서의 실행 결과


※ Mac을 가지고 있지 않기 때문에 iOS에서의 동작 확인은 실시하고 있지 않습니다.

요약



첨부 프로퍼티를 작성하는 것으로 이벤트에 Command 를 바인드 할 수가 있었습니다.
UWP와 유사한 방법에 대해서는 앞으로도 계속 조사하고 싶습니다.

이 기사에 기술한 소스는 GitHub에 프로젝트를 포함시켜 줍니다.
htps : // 기주 b. 코 m / 노리 마키 x ゔ ぃ / X 푹신 t ぇ dP 로 p mp

「01.Page.Appearing」이 이번 기사에 상당하는 것입니다.
「02.WebView.Navigated」는 추가로 WebView의 Navigated 이벤트등에도 대응하고 있습니다.

이번에 작성한 코드의 확인은 Xamarin.Forms v2.1.0.6529에서 실시했습니다.

좋은 웹페이지 즐겨찾기