💨

MAUIでアプリ作成(2)

2024/01/16に公開

MAUIサンプル

次は、コントロール間でBindingする方法です。

コントロールのプロパティをBinding

実装

さっそく、Bindするクラスを新規作成します。
クラス名は、「HslViewModel.cs」として下さい。
以後、実装にもHSLという言葉が頻発しますが、このHSLとは色の表現方法の一つみたいです。Hue(色相)、Saturation(彩度)、Lightness(輝度)らしいです。
HslViewModel.cs内の実装は以下の通り

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MauiSample
{
    class HslViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private float _hue, _saturation, _luminosity;
        private Color _color;

        public float Hue
        {
            get => _hue;
            set
            {
                if (_hue != value)
                    Color = Color.FromHsla(value, _saturation, _luminosity);
            }
        }
        public float Saturation
        {
            get => _saturation;
            set
            {
                if(Saturation != value)
                    Color = Color.FromHsla(_hue,value, _luminosity);
            }
        }
        public float Luminosity
        {
            get => _luminosity;
            set
            {
                if (_luminosity != value)
                    Color = Color.FromHsla(_hue, _saturation, value);
            }
        }
        public Color Color
        {
            get => _color;
            set
            {
                if(_color != value)
                {
                    _color = value;
                    _hue = _color.GetHue();
                    _saturation = _color.GetSaturation();
                    _luminosity = _color.GetLuminosity();

                    OnPropertyChanged("Hue");
                    OnPropertyChanged("Saturation");
                    OnPropertyChanged("Luminosity");
                    OnPropertyChanged();
                }
            }
        }
        public void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

前回と違って、各プロパティでOnPropertyChangedを呼ばずに、まとめて読んでいるとか、不思議な点がありますが、とりあえず動くところまで作ります。
次にこのクラスをバインドして使用する表示側の実装です。
MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MauiSample"
             x:Class="MauiSample.MainPage"
             Title="ClockPage Page">
    <ContentPage.BindingContext>
        <local:HslViewModel Color="Aqua" />
    </ContentPage.BindingContext>
    <VerticalStackLayout Padding="10, 0, 10, 30">
        <BoxView Color="{Binding Color}"
                 HeightRequest="100"
                 WidthRequest="100"
                 HorizontalOptions="Center" />
        <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Hue}"
                Margin="20,0,20,0" />
        <Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Saturation}"
                Margin="20,0,20,0" />
        <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Luminosity}"
                Margin="20,0,20,0" />
    </VerticalStackLayout>
</ContentPage>

これで実行してみると、とりあえず動いた。スクロールバーを変更すると、色が変化するので、スクロールバーのプロパティとBoxViewコントロールの色とは連動しているのがわかる。

本当にちなみになのですが、当初以下の記述で最後のOnPropertyChangedを記載忘れて、なぜかBoxViewの色が変わらず、少しだけ困った。

OnPropertyChanged("Hue");
OnPropertyChanged("Saturation");
OnPropertyChanged("Luminosity");
OnPropertyChanged();

検証

疑問であった、このOnPropertyChangedの使用に関して、検証してみよう。

まずは、固まっているOnPropertyChangedを、それぞれのプロパティに移動した。
Hueプロパティで言うと以下の感じ。他のSaturation、Luminosity、Colorも同様に修正した。

public float Hue
{
    get => _hue;
    set
    {
        if (_hue != value)
        {
            Color = Color.FromHsla(value, _saturation, _luminosity);
            OnPropertyChanged("Hue");
        }
    }
}

動きとしては、変わらないので、どっちでも良いのか?
Colorプロパティ内で、HueやSaturation変数は代入されているので、その先でOnPropertyChangedが呼ばれているので、結局処理としては同じと思われる。  
とすると、Colorプロパティ内で使用しているOnPropertyChanged();の意味が良くわからん。
OnPropertyChanged("Color");でダメな理由は?
ここは今後の宿題にしよう。どなたか強つよプログラマさん教えて下さい。

Discussion