MAUIでアプリ作成(2)
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