Share via


바인딩 값 변환기

Browse sample. 샘플 찾아보기

.NET 다중 플랫폼 앱 UI(.NET MAUI) 데이터 바인딩은 일반적으로 원본 속성에서 대상 속성으로 데이터를 전송하고 경우에 따라 대상 속성에서 원본 속성으로 데이터를 전송합니다. 이 전송은 원본 및 대상 속성이 동일한 형식인 경우 또는 하나의 형식을 암시적 변환을 통해 다른 형식으로 변환할 수 있는 경우에 간단합니다. 그렇지 않은 경우 형식 변환을 수행해야 합니다.

문자열 서식 문서에서는 데이터 바인딩의 속성을 사용하여 StringFormat 모든 형식을 문자열로 변환하는 방법을 알아보았습니다. 다른 형식의 변환의 경우 IValueConverter 인터페이스를 구현하는 클래스에 일부 특수한 코드를 작성해야 합니다. IValueConverter를 구현하는 클래스는 값 변환기라고 하지만 종종 바인딩 변환기 또는 바인딩 값 변환기라고도 합니다.

바인딩 값 변환기

원본 속성의 형식이 int이지만 대상 속성이 bool인 데이터 바인딩을 정의하려 한다고 가정합니다. 이 데이터 바인딩에서 정수 원본이 0인 경우 false 값을, 그렇지 않은 경우 true 값을 생성하기를 원합니다. 이 작업은 인터페이스를 구현하는 클래스를 IValueConverter 사용하여 수행할 수 있습니다.

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;
    }
}

그런 다음 이 클래스의 인스턴스를 Converter 클래스의 Binding 속성 또는 Converter 태그 확장의 속성으로 Binding 설정합니다. 이 클래스는 데이터 바인딩의 일부가 됩니다.

데이터가 원본에서 OneWay 또는 TwoWay 바인딩의 대상으로 이동하는 경우 Convert 메서드가 호출됩니다. value 매개 변수는 데이터 바인딩 원본의 개체 또는 값입니다. 메서드는 데이터 바인딩 대상 형식의 값을 반환해야 합니다. 여기에 표시된 메서드는 value 매개 변수를 int에 캐스팅한 다음, bool 반환 값에 대해 0과 비교합니다.

데이터가 대상에서 TwoWay 또는 OneWayToSource 바인딩의 원본으로 이동하는 경우 ConvertBack 메서드가 호출됩니다. ConvertBack은 반대 변환을 수행합니다. value 매개 변수가 대상의 bool이라고 가정하고, 원본에 대한 int 반환 값으로 변환합니다.

참고 항목

데이터 바인딩에 설정도 포함된 StringFormat 경우 결과 형식이 문자열로 지정되기 전에 값 변환기가 호출됩니다.

다음 예제에서는 데이터 바인딩에서 이 값 변환기를 사용하는 방법을 보여 줍니다.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.EnableButtonsPage"
             Title="Enable Buttons">
    <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>

이 예제에서는 IntToBoolConverter 페이지의 리소스 사전에서 인스턴스화됩니다. 그런 다음 태그 확장으로 StaticResource 참조되어 두 데이터 바인딩에서 속성을 설정합니다 Converter . 페이지의 여러 데이터 바인딩 간에 데이터 변환기를 공유하는 것은 매우 일반적입니다. 애플리케이션의 여러 페이지에서 값 변환기를 사용하는 경우 애플리케이션 수준 리소스 사전에서 인스턴스화할 수 있습니다.

이 예제에서는 사용자가 뷰에 입력 Entry 하는 Button 텍스트를 기반으로 작업을 수행할 때의 일반적인 필요성을 보여 줍니다. 속성은 Text 기본적으로 이 경우 데이터 바인딩이 작동하지 않으므로 각 Entry 속성이 null 빈 문자열 Text 로 초기화됩니다. Entry에 아무 것도 입력되지 않은 경우 Button은 비활성화되어야 합니다. 각 Button은 해당 IsEnabled 속성에 데이터 바인딩을 포함합니다. 데이터 바인딩 원본은 해당 EntryText 속성의 Length 속성입니다. 해당 Length 속성이 0이 아닌 경우 값 변환기는 true를 반환하며 Button이 활성화됩니다.

Enable buttons.

참고 항목

값 변환기가 OneWay 바인딩에서만 사용된다는 것을 아는 경우 ConvertBack 메서드는 간단하게 null을 반환할 수 있습니다.

위에 표시된 메서드는 Convert 인수가 value 형식이고 반환 값이 형식 intbool이어야 한다고 가정합니다. 마찬가지로 ConvertBack 메서드는 value 인수가 bool 형식이며 반환 값은 int라는 것을 가정합니다. 그렇지 않은 경우 런타임 예외가 발생합니다.

값 변환기를 보다 일반화되고 여러 다른 유형의 데이터를 허용하도록 작성할 수 있습니다. ConvertConvertBack 메서드는 value 매개 변수와 함께 as 또는 is 연산자를 사용하거나 해당 매개 변수에서 GetType을 호출하여 해당 형식을 결정한 다음, 적절한 작업을 수행할 수 있습니다. 각 메서드의 반환 값의 예상 형식은 targetType 매개 변수에서 지정됩니다. 경우에 따라 값 변환기는 서로 다른 대상 형식의 데이터 바인딩과 함께 사용됩니다. 이 경우 값 변환기는 인수를 targetType 사용하여 올바른 형식에 대한 변환을 수행할 수 있습니다.

수행되는 변환이 다른 문화권과 다른 경우 이 목적을 위해 culture 매개 변수를 사용합니다.

바인딩 변환기 속성

값 변환기 클래스에는 속성 및 일반 매개 변수가 있을 수 있습니다. 다음 값 변환기는 원본에서 대상의 형식 T 개체로 변환 bool 합니다.

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는 제네릭 인수를 나타내며, TrueObjectFalseObject는 해당 형식의 개체로 설정됩니다.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.SwitchIndicatorsPage"
             Title="Switch Indicators">
    <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>

이 예제에서는 세 SwitchLabel 쌍의 마지막에서 제네릭 인수가 aStyle로 설정되고 값에 대한 FalseObjectTrueObject 전체 Style 개체가 제공됩니다. 이는 리소스 사전에 설정된 Label에 대한 암시적 스타일을 재정의하므로 해당 스타일의 속성은 Label에 명시적으로 할당됩니다. Switch를 설정/해제하면 해당 Label에 변경 내용이 반영됩니다.

Switch indicators.

참고 항목

트리거를 사용하여 다른 보기에 따라 사용자 인터페이스의 변경 내용을 구현할 수도 있습니다. 자세한 내용은 트리거를 참조하세요.

바인딩 변환기 매개 변수

Binding 클래스는 ConverterParameter 속성을 정의하며, Binding 태그 확장도 ConverterParameter 속성을 정의합니다. 이 속성이 설정되어 있는 경우 값은 parameter 인수로 ConvertConvertBack 메서드에 전달됩니다. 값 변환기의 인스턴스가 여러 데이터 바인딩 ConverterParameter 간에 공유되더라도 서로 다른 변환을 수행하도록 다를 수 있습니다.

색 선택 프로그램을 사용하여 속성을 사용할 ConverterParameter 수 있습니다. 다음 예제에서는 이름이 지정된 RedGreen형식 float 의 속성 세 개와 Blue 값을 생성하는 Color 데 사용하는 속성을 보여 RgbColorViewModel있습니다.

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"));
            }
        }
    }
}

, GreenBlue 속성 값의 범위는 Red0에서 1 사이일 수 있습니다. 그러나 두 자리 16진수 값으로 구성 요소를 표시하는 것을 선호할 수 있습니다. XAML에서 16진수 값으로 표시하려면 255를 곱하고, 정수로 변환한 다음, StringFormat 속성에서 "X2"의 사양으로 형식을 지정해야 합니다. 값 변환기에서 255를 곱하고 정수로 변환할 수 있습니다. 값 변환기를 최대한 일반화하기 위해 ConverterParameter 속성으로 곱하기 비율을 지정할 수 있습니다. 즉, parameter 인수로 ConvertConvertBack 메서드를 입력합니다.

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;
    }
}

이 예제에서 메서드는 Convert 값을 곱하는 parameter 동안에서 floatint 변환합니다. 이 메서드는 ConvertBackvalue 수 인수를 구분하여 parameter 결과를 반환합니다 float .

인수의 parameter 형식은 데이터 바인딩이 XAML 또는 코드에 정의되어 있는지 여부에 따라 다를 수 있습니다. BindingConverterParameter 속성이 코드에서 설정된 경우 숫자 값으로 설정될 수 있습니다.

binding.ConverterParameter = 255;

ConverterParameter 속성은 Object 형식이므로 C# 컴파일러는 정수로 리터럴 255를 해석하고, 해당 값으로 속성을 설정합니다.

그러나 XAML ConverterParameter 에서는 다음과 같이 설정될 수 있습니다.

<Label Text="{Binding Red,
                      Converter={StaticResource doubleToInt},
                      ConverterParameter=255,
                      StringFormat='Red = {0:X2}'}" />

255는 숫자 ConverterParameter 처럼 보이지만 형식 Object이므로 XAML 파서는 255를 문자열로 처리합니다. 이러한 이유로 값 변환기는 형식 floatint또는 형식에 대 한 parameter 대/소문자를 처리 하는 별도 GetParameter 메서드를 string포함 합니다.

다음 XAML 예제는 리소스 사전에서 인스턴스화 FloatToIntConverter 합니다.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.RgbColorSelectorPage"
             Title="RGB Color Selector">
    <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>

RedGreen 속성의 값은 Binding 태그 확장으로 표시됩니다. 그러나 이 속성은 Blue 클래스를 Binding 인스턴스화하여 명시적 float 값을 속성으로 ConverterParameter 설정하는 방법을 보여 줍니다.

RGB color selector.