형식이 일치하지 않는 데이터 바인딩

완료됨

사용 중인 데이터가 데이터를 표시하는 컨트롤 속성의 데이터 형식과 일치하지 않는 경우가 있습니다. 예를 들어 decimal 형식으로 저장된 화폐 값을 통화 형식으로 Label 컨트롤에 표시하려고 할 수 있습니다. 더 복잡한 예제는 모듈에 표시되는 날씨 앱입니다. 일기 예보의 Sunny 또는 Cloudy 열거형 값에 따라 이미지를 표시해야 하지만 원본의 열거형 값을 대상의 이미지 속성에 바인딩할 수 없습니다. 이 단원에서는 데이터를 변환할 수 있는 방법을 살펴봅합니다.

문자열 서식 지정

형식 불일치의 대표적인 사례는 서식이 지정된 문자열로 표시하려는 내장 형식입니다. DateTime 값의 일부를 표시하거나 decimal 형식을 통화로 지정하려는 경우와 같습니다.

청구된 금액을 표시하고 데이터 개체에 이 속성이 있다고 가정해 보세요.

public decimal BillAmount { get; set; }

청구된 금액은 22.0304가 됩니다. 다음 코드 조각에 설명된 대로 두 개의 레이블 컨트롤을 사용하여 일부 텍스트와 달러 금액을 표시할 수 있습니다.

<HorizontalStackLayout>
    <Label Text="You owe" Margin="0,0,5,0" />
    <Label Text="{Binding BillAmount}" />
    <Label Text="to the bank" Margin="5,0,0,0" />
</HorizontalStackLayout>

이렇게 하면 You owe 22.0304 to the bank처럼 보이는 문자열이 UI에 출력되지만 통화 기호가 누락되었으며 현지 통화에 따라 소수 자릿수가 너무 많거나 너무 적을 수 있습니다. 일반적으로 다음과 같이 코드에서 "C"(또는 통화) 형식 지정자를 사용하여 값을 문자열로 처리합니다.

string formattedBillAmount = string.Format("{0:C}", BillAmount);

그러나 데이터 바인딩에서 서식을 사용하려면 데이터 개체가 형식이 지정된 문자열을 다른 속성으로 제공하도록 하거나 어떻게든 중간에 직접 서식을 지정해야 합니다. 다행히 .NET MAUI 바인딩은 StringFormat 바인딩 속성을 사용하여 문자열의 서식을 지정하는 방법을 제공합니다. 이 서식 문자열은 String.Format 메서드와 동일한 규칙을 따릅니다. XAML 파서가 중괄호 때문에 혼동하지 않도록 서식 문자열을 작은 따옴표로 묶습니다. 문자열 형식 매개 변수 0은 바인딩에 의해 처리되는 속성 값입니다.

<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />

두 가지 방법으로 BillAmount를 표시하는 경우를 보여 주는 다음 XAML을 고려해 보세요.

<VerticalStackLayout Padding="10">
    <HorizontalStackLayout>
        <Label Text="You owe" Margin="0,0,5,0" />
        <Label Text="{Binding BillAmount}" />
        <Label Text="to the bank" Margin="5,0,0,0" />
    </HorizontalStackLayout>
    <HorizontalStackLayout>
        <Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
    </HorizontalStackLayout>
</VerticalStackLayout>

다음 이미지는 XAML 출력이 화면에서 생성하는 결과를 보여 줍니다.

비용 청구와 관련된 텍스트를 포함하는 두 개의 다른 레이블을 표시하는 .NET MAUI Android 앱 스크린샷 한 레이블의 텍스트는 USD 통화로 서식이 지정되어 있습니다.

StringFormat 바인딩 속성을 사용하는 XAML은 다른 XAML보다 더 간단하며, .NET의 강력한 문자열 서식 시스템에 액세스할 수 있습니다.

사용자 지정 형식 변환

StringFormat 바인딩 속성은 값을 문자열로 표시할 때 편리하지만 다른 형식에서 Color 또는 Image와 같은 항목을 변환하려는 경우에는 편리하지 않습니다. 이러한 경우에는 사용자 지정 변환 코드를 작성해야 합니다.

암호를 변경하라는 메시지가 표시되며, UI에서 색을 사용하여 암호 강도를 표시하려고 합니다. 암호 강도에는 약함, 양호, 강력함의 세 가지 수준이 있습니다. 강도는 암호에 포함된 문자 수를 기준으로 결정됩니다. 사용자에게 암호 강도에 대한 즉각적인 피드백을 제공하기 위해 암호 강도에 따라 암호가 포함된 Entry 컨트롤의 배경이 바뀌도록 할 수 있습니다. 다음 이미지는 세 가지 강도인 약함, 양호 및 강력함을 보여 줍니다.

다른 배경색을 갖는 세 가지 입력 컨트롤이 있는 .NET MAUI Android 앱 스크린샷

스크린샷에 표시된 세 가지 입력 컨트롤 중에서 첫 번째 컨트롤에 3개 문자가 입력되고 빨간색 배경이 표시됩니다. 두 번째 컨트롤에는 9개 문자가 입력되고 노란색 배경이 있습니다. 마지막 입력 컨트롤에는 15개 문자가 입력되고 파란색 배경이 있습니다.

다음 수준이 Strength 열거형에 할당됩니다.

private enum Strength
{
    Weak,
    Good,
    Strong
}

데이터 개체가 페이지의 BindingContext에 할당되며, 여기에는 PasswordStrength 속성의 암호 강도가 포함됩니다. 사용자가 암호를 입력하면 암호 길이에 따라 PasswordStrength 속성이 변경됩니다. 데이터 개체에 PasswordStrength 속성이 포함되어 있으므로 해당 속성을 Entry 컨트롤의 BackgroundColor에 바인딩합니다.

<Entry BackgroundColor="{Binding PasswordStrength} ... />

하지만 여기에는 문제가 있습니다. PasswordStrengthStrength 형식이지만 BackgroundColorColor 형식입니다. 이러한 형식은 서로 호환되지 않습니다. .NET MAUI는 이러한 형식 불일치 문제를 수정할 수 있는 방법인 바인딩의 Converter 속성을 제공합니다.

바인딩 변환기는 이름이 의미하는 것처럼 바인딩 원본과 바인딩 대상 간을 변환합니다. 변환기는 IValueConverter 인터페이스를 통해 구현됩니다.

IValueConverter 구현

변환 논리를 IValueConverter 인터페이스를 구현하는 클래스로 만듭니다. 일반적으로 이러한 클래스의 이름은 용도를 명확하게 하기 위해 Converter 이름으로 끝납니다.

IValueConverter 인터페이스는 다음 두 가지 메서드를 정의합니다.

  • Convert—바인딩 원본의 속성에서 바인딩 대상의 UI 속성으로 변환합니다.

  • ConvertBack—바인딩 대상의 UI 속성을 바인딩 원본의 속성으로 다시 변환합니다.

    이 메서드는 거의 사용되지 않으며 이 시나리오에서는 사용되지 않습니다. 대부분의 변환기는 이 변환이 지원되지 않음을 나타내기 위해 NotSupportedException을 throw합니다.

인터페이스의 계약은 다음과 같습니다.

public interface IValueConverter
{
    object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
    object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}

다시 말하지만 작업 중인 시나리오는 Entry.BackgroundColor 속성을 Strength 열거형인 데이터 개체의 PasswordStrength 속성에 바인딩하는 것입니다.

<Entry BackgroundColor="{Binding PasswordStrength} ... />

Strength 열거형을 Color로 변환해야 합니다. 따라서 변환기는 제공되는 Strength 값을 평가하고 다른 Color를 반환해야 합니다. 다음 코드는 이 변환을 보여 줍니다.

namespace MyProject.Converters;

class StrengthToColorConverter : IValueConverter
{
    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        return (Strength)value! switch
        {
            Strength.Weak => Colors.OrangeRed,
            Strength.Good => Colors.Yellow,
            Strength.Strong => Colors.LightBlue,
            _ => Colors.LightBlue
        };
    }

    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
        throw new NotImplementedException();
}

이 코드를 분석해 보겠습니다.

  • Convert 메서드는 네 개의 매개 변수를 사용합니다. 마지막 두 매개 변수는 사용할 특별한 이유가 있지 않다면 취소할 수 있습니다.
  • value 매개 변수에는 들어오는 값이 포함됩니다. 이 예제에서는 Strength 열거형 값입니다.
  • targetType 매개 변수는 무시됩니다. 그렇지만 이 매개 변수를 사용하여 변환기가 사용되는 속성 형식이 Color인지 확인할 수 있었습니다. 단순성을 위해 이 예제에서는 생략됩니다.
  • Strength 값에 따라 다른 색을 반환하기 위해 switch 식이 사용됩니다.

XAML에서 변환기 사용

변환기 클래스가 만들어지면 해당 인스턴스를 만들고 바인딩에서 참조해야 합니다. 변환기를 인스턴스화하는 표준 방법은 루트 요소의 리소스 사전에 있습니다.

먼저 XML 네임스페이스를 변환기가 포함된 .NET 네임스페이스에 매핑합니다. 다음 코드 예제에서 cvt XML 네임스페이스는 MyProject.Converters .NET 네임스페이스에 매핑됩니다.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:cvt="clr-namespace:MyProject.Converters"
             ...

다음으로, ContentPage.Resources에서 인스턴스를 만듭니다.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:cvt="clr-namespace:MyProject.Converters"
             x:Class="MyProject.PasswordExample">
    <ContentPage.Resources>
        <cvt:StrengthToColorConverter x:Key="StrengthToColorConverter" />
    </ContentPage.Resources>

이제 변환기 인스턴스는 형식과 이름이 같은 키 StrengthToColorConverter가 있는 리소스 사전에 있습니다. 이 방법으로 변환기의 이름을 지정하면 XAML 전체에서 다시 사용하게 되는 단일 변환기를 유지하게 되므로 일반적입니다. 일부 이유로 여러 변환기 인스턴스가 필요한 경우 키를 사용해서 구분해야 합니다.

마지막으로 바인딩에서 변환기를 참조합니다. 변환기는 리소스 사전에 있으므로 {StaticResource} 태그 확장을 사용하여 참조합니다. 변환기는 Converter 바인딩 속성에 할당됩니다.

<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />

지식 점검

1.

데이터 바인딩에서 값을 문자열로 표시하고 서식을 지정할 경우 가장 좋은 접근 방식은 무엇인가요?

2.

데이터 바인딩 변환에서는 어떤 형식이 사용되나요?