takataka430’s blog

.NET系を中心に勉強したことのまとめを書きます

【Xamarin.Forms】ViewModelでContentViewとFrameを操作してDisplayAlertの代わりにできないか試してみた

ViewModelで悩むことの一つとして「DisplayAlertを呼び出せない」というのがあると思います。色々解決方法を考えていて、「もしかしてContentViewとFrameを使えばDisplayAlertの代わりになるのでは??」と思いついたのでやってみたメモです。
(ライブラリやフレームワークは使わずに素のXamarin.Formsでやってみました)

コード

次のように書いてみました。(コードビハインドはInitializeComponentのみなので省略します)

画面

<?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:AlertFromViewModel" 
             x:Class="AlertFromViewModel.MainPage">
    <ContentPage.BindingContext>
        <local:MainPageViewModel/>
    </ContentPage.BindingContext>
    <AbsoluteLayout>
        <Button Text="Alert" 
                AbsoluteLayout.LayoutFlags="PositionProportional"
                AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
                HorizontalOptions="Center" 
                VerticalOptions="CenterAndExpand" 
                Command="{Binding OnAlert}"/>
        <ContentView AbsoluteLayout.LayoutFlags="All"
                     AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
                     Opacity="0.4"
                     BackgroundColor="Black"
                     IsVisible="{Binding IsVisible}"/>
        <Frame AbsoluteLayout.LayoutFlags="PositionProportional"
               AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
               IsVisible="{Binding IsVisible}">
            <StackLayout>
                <Label Text="アラートです"
                       HorizontalTextAlignment="Center"/>
                <Button Text="OK"
                        Command="{Binding OnOK}"/>
            </StackLayout>
        </Frame>        
    </AbsoluteLayout>
</ContentPage>

  
ビューモデル

using System.ComponentModel;
using Xamarin.Forms;

namespace AlertFromViewModel
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public MainPageViewModel()
        {
            OnOK = new Command(() =>
            {
                IsVisible = false;
            });

            OnAlert = new Command(() =>
            {
                IsVisible = true;
            });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private bool isVisible;
        public bool IsVisible
        {
            get { return isVisible; }
            set
            {
                if(isVisible != value)
                {
                    isVisible = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsVisible)));
                }
            }
        }

        public Command OnOK { get; }

        public Command OnAlert { get; }
    }
}

画面の「Alert」ボタンを押すとContentViewとFrameが表示されます。その後Frameの「OK」ボタンを押すとContentViewとFrameが非表示になり、元の画面に戻ります。

動きはこんな感じです!

f:id:takataka430:20190324230137g:plain:w200

アラートっぽくなりましたね!
  
・・・でも正直ちょっと面倒なので、素直にコードビハインドに書くかライブラリを使った方がいいのかなと思いました。