2022. 7. 28. 00:00ㆍMAUI
.NET 다중 플랫폼 앱 UI(.NET MAUI) 데이터 바인딩은 일반적으로 원본 속성에서 대상 속성으로 데이터를 전송하고 경우에 따라 대상 속성에서 원본 속성으로 데이터를 전송한다. 이 전송은 소스 및 대상 속성이 동일한 유형이거나 암시적 변환을 통해 한 유형을 다른 유형으로 변환할 수 있는 경우에 간단하다. 그렇지 않은 경우 형식 변환이 발생한다.
데이터 바인딩의 StringFormat 속성을 사용하여 모든 유형을 문자열로 변환할 수 있다.
다른 유형의 변환의 경우 IValueConverter 인터페이스를 구현하는 클래스에 일부 특수 코드를 작성해야 한다.
소스 속성이 int 유형이지만 대상 속성이 bool인 데이터 바인딩을 정의하려고 한다고 가정하자.
정수 소스가 0과 같을 때 이 데이터 바인딩이 false 값을 생성하고 그렇지 않으면 true를 생성한다.
public class IntToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value != 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? 1 : 0;
}
}
그리고 이 내용을 Button 을 enable 하거나 disable 하는 다음 XAML Page 에 적용해보자
<?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"
x:Class="MauiApp1.Xaml.ValueConverter.EnableButtonPage"
xmlns:local ="clr-namespace:MauiApp1.Xaml.ValueConverter"
Title="EnableButtonPage">
<ContentPage.Resources>
<local:IntToBoolConverter x:Key="intToBool" />
</ContentPage.Resources>
<StackLayout Padding="10, 0">
<Entry x:Name="entry1"
Text=""
Placeholder="enter search term"
VerticalOptions="Center" />
<Button Text="Search"
HorizontalOptions="Center"
VerticalOptions="Center"
IsEnabled="{Binding Source={x:Reference entry1},
Path=Text.Length,
Converter={StaticResource intToBool}}" />
<Entry x:Name="entry2"
Text=""
Placeholder="enter destination"
VerticalOptions="Center" />
<Button Text="Submit"
HorizontalOptions="Center"
VerticalOptions="Center"
IsEnabled="{Binding Source={x:Reference entry2},
Path=Text.Length,
Converter={StaticResource intToBool}}" />
</StackLayout>
</ContentPage>
실행화면
Convert 는 int 형식을 bool 형식으로 변환하고
ConvertBack 는 bool 형식을 int 로 변환한다.
Convert 는 Entry 에 입력 값의 길이가 source 이고 Button 의 IsEnabled 가 target 이 된다.
ConvertBack 은 반대로 생각하면 쉽다.
또한 Value Converter 는 속성과 매개변수가 있을 수 있다.
다음 Converter 는 소스의 bool 을 대상에 T 형태로 변환한다.
public class BoolToObjectConverter<T> : IValueConverter
{
public T TrueObject { get; set; }
public T FalseObject { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? TrueObject : FalseObject;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((T)value).Equals(TrueObject);
}
}
다음 예는 이 변환기를 사용하여 Switch 보기의 값을 표시하는 방법을 보여준다.
여기에서 각 값 변환기는 Binding.Converter 속성 요소 태그 간에 인스턴스화된다.
x:TypeArguments는 generic argument 를 나타내며 TrueObject 및 FalseObject는 모두 해당 유형의 개체로 설정된다.
<?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"
x:Class="MauiApp1.Xaml.ValueConverter.SwitchIndicatorsPage"
xmlns:local="clr-namespace:MauiApp1.Xaml.ValueConverter"
Title="SwitchIndicatorsPage">
<ContentPage.Resources>
<Style TargetType="Label">
<Setter Property="FontSize" Value="18" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>
<Style TargetType="Switch">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ContentPage.Resources>
<StackLayout Padding="10, 0">
<StackLayout Orientation="Horizontal"
VerticalOptions="Center">
<Label Text="Subscribe?" />
<Switch x:Name="switch1" />
<Label>
<Label.Text>
<Binding Source="{x:Reference switch1}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="x:String"
TrueObject="Of course!"
FalseObject="No way!" />
</Binding.Converter>
</Binding>
</Label.Text>
</Label>
</StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="Center">
<Label Text="Allow popups?" />
<Switch x:Name="switch2" />
<Label>
<Label.Text>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="x:String"
TrueObject="Yes"
FalseObject="No" />
</Binding.Converter>
</Binding>
</Label.Text>
<Label.TextColor>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="Color"
TrueObject="Green"
FalseObject="Red" />
</Binding.Converter>
</Binding>
</Label.TextColor>
</Label>
</StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="Center">
<Label Text="Learn more?" />
<Switch x:Name="switch3" />
<Label FontSize="18"
VerticalOptions="Center">
<Label.Style>
<Binding Source="{x:Reference switch3}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="Style">
<local:BoolToObjectConverter.TrueObject>
<Style TargetType="Label">
<Setter Property="Text" Value="Indubitably!" />
<Setter Property="FontAttributes" Value="Italic, Bold" />
<Setter Property="TextColor" Value="Green" />
</Style>
</local:BoolToObjectConverter.TrueObject>
<local:BoolToObjectConverter.FalseObject>
<Style TargetType="Label">
<Setter Property="Text" Value="Maybe later" />
<Setter Property="FontAttributes" Value="None" />
<Setter Property="TextColor" Value="Red" />
</Style>
</local:BoolToObjectConverter.FalseObject>
</local:BoolToObjectConverter>
</Binding.Converter>
</Binding>
</Label.Style>
</Label>
</StackLayout>
</StackLayout>
</ContentPage>
이 예에서 세 개의 Switch 및 Label 쌍 중 마지막에서 generic argument가 Style로 설정되고 TrueObject 및 FalseObject 값에 대해 전체 Style 개체가 제공된다. 이들은 리소스 사전에 설정된 Label의 암시적 스타일을 재정의하므로 해당 스타일의 속성이 명시적으로 Label에 할당된다. 스위치를 토글하면 해당 레이블에 변경 사항이 반영된다.
Value Converter 를 이용해 Convert 시에 Parameter 를 전달 할 수 있다.
이것을 Converter parameters 라고 한다.
using MauiApp1.Xaml.BindingMode;
using System.ComponentModel;
namespace MauiApp1.Xaml.ValueConverter;
public class RgbColorViewModel : INotifyPropertyChanged
{
Color color;
string name;
public event PropertyChangedEventHandler PropertyChanged;
public float Red
{
get { return color.Red; }
set
{
if (color.Red != value)
{
Color = new Color(value, color.Green, color.Blue);
}
}
}
public float Green
{
get { return color.Green; }
set
{
if (color.Green != value)
{
Color = new Color(color.Red, value, color.Blue);
}
}
}
public float Blue
{
get { return color.Blue; }
set
{
if (color.Blue != value)
{
Color = new Color(color.Red, color.Green, value);
}
}
}
public Color Color
{
get { return color; }
set
{
if (color != value)
{
color = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Red"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Green"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Blue"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
Name = NamedColor.GetNearestColorName(color);
}
}
}
public string Name
{
get { return name; }
private set
{
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
NamedColor 은 이전 강의 Bining Mode 에 있습니다.
R , G, B 값의 범위는 0과 1 사이 일 수 있다. 그러나 우리는 16진수 값에 더 익숙 하다.
그러므로 16진수 값으로 표시하기 위해 255 를 곱해서 정수로 변환한 다음
StringFormat 의 "X2" 를 이용하여 형식을 지정해 주면 된다.
값 변환기를 최대한 일반화하려면 ConverterParameter 속성을 사용하여 곱셈 인수를 지정할 수 있다.
즉, Convert 및 ConvertBack 메서드가 매개 변수 인수로 입력된다.
using System.Globalization;
namespace MauiApp1.Xaml.ValueConverter;
public class FloatToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)Math.Round((float)value * GetParameter(parameter));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value / GetParameter(parameter);
}
double GetParameter(object parameter)
{
if (parameter is float)
return (float)parameter;
else if (parameter is int)
return (int)parameter;
else if (parameter is string)
return float.Parse((string)parameter);
return 1;
}
}
XAML 에서는 다음과 같이 사용할 수 있다.
<Label Text="{Binding Red,
Converter={StaticResource doubleToInt},
ConverterParameter=255,
StringFormat='Red = {0:X2}'}" />
255는 숫자처럼 보이지만 ConverterParameter는 Object 유형이므로 XAML 파서는 255를 문자열로 처리한다.
이러한 이유로 값 변환기에는 매개변수가 float, int 또는 string 유형인 경우를 처리하는
별도의 GetParameter 메서드가 포함되어 있다.
<?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"
x:Class="MauiApp1.Xaml.ValueConverter.RgbColorSelectorPage"
xmlns:local="clr-namespace:MauiApp1.Xaml.ValueConverter"
Title="RgbColorSelectorPage">
<ContentPage.BindingContext>
<local:RgbColorViewModel Color="Gray" />
</ContentPage.BindingContext>
<ContentPage.Resources>
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<local:FloatToIntConverter x:Key="floatToInt" />
</ContentPage.Resources>
<StackLayout Margin="20">
<BoxView Color="{Binding Color}"
HeightRequest="100"
WidthRequest="100"
HorizontalOptions="Center" />
<StackLayout Margin="10, 0">
<Label Text="{Binding Name}" />
<Slider Value="{Binding Red}" />
<Label Text="{Binding Red,
Converter={StaticResource floatToInt},
ConverterParameter=255,
StringFormat='Red = {0:X2}'}" />
<Slider Value="{Binding Green}" />
<Label Text="{Binding Green,
Converter={StaticResource floatToInt},
ConverterParameter=255,
StringFormat='Green = {0:X2}'}" />
<Slider Value="{Binding Blue}" />
<Label>
<Label.Text>
<Binding Path="Blue"
StringFormat="Blue = {0:X2}"
Converter="{StaticResource floatToInt}">
<Binding.ConverterParameter>
<x:Single>255</x:Single>
</Binding.ConverterParameter>
</Binding>
</Label.Text>
</Label>
</StackLayout>
</StackLayout>
</ContentPage>
Red 및 Green 속성 값은 Binding 태그 확장과 함께 표시된다.
그러나 Blue 속성은 Binding 클래스를 인스턴스화하여
명시적 float 값을 ConverterParameter 속성으로 설정할 수 있는 방법을 보여준다.
실행
관련영상
'MAUI' 카테고리의 다른 글
.NET MAUI - Binding Command (0) | 2022.08.01 |
---|---|
.NET MAUI - Binding Relative bindings (0) | 2022.07.29 |
.NET MAUI - Binding 경로 (Path) (0) | 2022.07.27 |
.NET MAUI - Binding 모드 (0) | 2022.07.26 |
.NET MAUI - Binding 기본 (0) | 2022.07.25 |