ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • WPF Converter (컨버터, 값 변환기)
    닷넷/WPF 2023. 6. 9. 15:06
    반응형

    Converter

    WPF에서 Converter는 WPF의 핵심 기능 중 하나인 데이터 바인딩에서 데이터를 바인딩하는 동안 값의 변환을 수행하는 데 사용되는 기능입니다. Converter를 사용하면 데이터를 원하는 형식으로 변환하거나, 값을 가공하여 UI 요소에 표시할 수 있습니다.

    예를 들어, bool 값을 "예" 또는 "아니오"로 변환하거나, 숫자를 포맷팅하거나, 날짜 형식을 변경하는 등의 작업을 수행할 수 있습니다.

     

     

    사용방법

    Converter는 IValueConverter 또는 IMultiValueConverter 인터페이스를 구현하는 클래스로 작성됩니다. IValueConverter는 단일 값을 변환하는 데 쓰이며, IMultiValueConverter는 여러 값을 조합하여 변환하는 데 쓰입니다.

    이 인터페이스에는 두 개의 메서드가 있습니다.

    1. Convert

    데이터 소스에서 UI 요소로 값이 전달될 때 호출되는 메서드입니다. 이 메서드는 변환된 값을 반환합니다. 예를 들어, 숫자를 문자열로 변환하거나, 날짜 형식을 변경하거나, 열거형 값을 텍스트로 변환하는 등의 작업을 수행할 수 있습니다.

    2. ConvertBack

    UI 요소에서 데이터 소스로 값이 전달될 때 호출되는 메서드입니다. 이 메서드는 다시 원래의 값으로 변환된 값을 반환합니다. 예를 들어, 문자열을 숫자로 변환하거나, 텍스트를 열거형 값으로 변환하는 등의 작업을 수행할 수 있습니다.

     

    데이터 바인딩 표현식에서 Converter를 사용하여 데이터를 변환하는 방법은 다음과 같습니다.

    <TextBlock Text="{Binding MyProperty, Converter={StaticResource MyConverter}}" />

    위의 예시에서 "MyProperty"는 데이터 소스의 속성을 나타내며, "MyConverter"는 리소스로 선언된 Converter의 이름입니다. Converter는 데이터 소스로부터 값을 가져와서 필요한 변환 작업을 수행한 후에 UI 요소에 표시됩니다.

     

     

    Converter 종류 및 코드 예시

    어떤 것이든 IValueConverter 또는 IMultiValueConverter 인터페이스를 상속해서 직접 만들어도 되며, 몇 가지 일반적인 Converter의 종류는 다음과 같습니다.

    1. BooleanConverter

    논리값을 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, true/false 값을 Yes/No 문자열로 변환하거나 Visibility로 변환하는 등의 작업을 수행할 수 있습니다.

    <!-- Boolean 값을 "Yes" 또는 "No"로 변환하는 예시 -->
    <Window.Resources>
        <local:BooleanToYesNoConverter x:Key="BooleanToYesNoConverter" />
    </Window.Resources>
    <TextBlock Text="{Binding IsEnabled, Converter={StaticResource BooleanToYesNoConverter}}" />
    public class BooleanToYesNoConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool boolValue)
            {
                return boolValue ? "Yes" : "No";
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    <!-- Boolean 값을 컨트롤의 가시성을 뜻하는 Visibility 속성으로 변환하는 예시 -->
    <Window.Resources>
        <local:VisibilityConverter x:Key="VisibilityConverter" />
    </Window.Resources>
    <Grid>
        <TextBlock Text="Hello, World!" Visibility="{Binding IsVisible, Converter={StaticResource VisibilityConverter}}" />
    </Grid>
    public class VisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool boolValue)
            {
                return boolValue ? Visibility.Visible : Visibility.Collapsed;
            }
            return Binding.DoNothing;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is Visibility visibilityValue)
            {
                return visibilityValue == Visibility.Visible;
            }
            return Binding.DoNothing;
        }
    }

     

    2. StringConverter

    문자열을 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, 숫자를 문자열로 변환하거나, 문자열의 대소문자를 변경하는 등의 작업을 수행할 수 있습니다.

    <!-- 숫자를 문자열로 변환하는 예시 -->
    <TextBlock Text="{Binding Quantity, Converter={StaticResource NumberToStringConverter}}" />
    public class NumberToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int intValue)
            {
                return intValue.ToString();
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    3. DateTimeConverter

    날짜와 시간을 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, 날짜 형식을 변경하거나, 날짜와 시간 사이의 차이를 계산하는 등의 작업을 수행할 수 있습니다.

    <!-- 날짜 형식을 변경하는 예시 -->
    <TextBlock Text="{Binding BirthDate, Converter={StaticResource DateTimeFormatConverter}, ConverterParameter='yyyy-MM-dd'}" />
    public class DateTimeFormatConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is DateTime dateValue && parameter is string format)
            {
                return dateValue.ToString(format);
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    4. EnumConverter

    열거형 값을 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, 열거형 값을 문자열로 변환하거나, 문자열을 열거형 값으로 변환하는 등의 작업을 수행할 수 있습니다.

    <!-- 열거형 값을 문자열로 변환하는 예시 -->
    <TextBlock Text="{Binding Status, Converter={StaticResource EnumToStringConverter}}" />
    public class EnumToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is Enum enumValue)
            {
                return enumValue.ToString();
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    5. ColorConverter

    색상을 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, 색상을 RGB 값으로 변환하거나, RGB 값을 색상으로 변환하는 등의 작업을 수행할 수 있습니다.

    <!-- SolidColorBrush를 Color로 변환하는 예시 -->
    <TextBlock Foreground="{Binding StatusColor, Converter={StaticResource SolidColorBrushToColorConverter}}" />
    public class SolidColorBrushToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is SolidColorBrush brush)
            {
                return brush.Color;
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    6. ValueConverter

    값의 형식을 변환하는 데 사용됩니다. 이는 가장 일반적으로 사용되는 Converter입니다. 예를 들어, 숫자를 포맷팅하거나, 값의 범위를 제한하는 등의 작업을 수행할 수 있습니다.

    <!-- 숫자를 포맷팅하는 예시 -->
    <TextBlock Text="{Binding Price, Converter={StaticResource CurrencyConverter}}" />
    public class CurrencyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is decimal decimalValue)
            {
                return decimalValue.ToString("C", culture); // 통화 형식으로 변환
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    7. MultiValueConverter

    여러 개의 값을 변환하는 데 사용됩니다. 여러 데이터 소스의 값을 조합하여 하나의 값으로 변환할 수 있습니다. 예를 들어, 두 숫자를 합치거나, 여러 개의 속성을 결합하여 문자열을 생성하는 등의 작업을 수행할 수 있습니다.

    <!-- 두 개의 값을 합치는 예시 -->
    <TextBlock>
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource AdditionConverter}">
                <Binding Path="Value1" />
                <Binding Path="Value2" />
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>
    public class AdditionConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length == 2 && values[0] is double value1 && values[1] is double value2)
            {
                return value1 + value2;
            }
            return Binding.DoNothing;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    8. DataTriggerConverter

    데이터 바인딩 트리거에 사용되는 Converter입니다. 데이터 바인딩 값에 따라 UI 요소의 속성을 변경하는 데 사용됩니다. 예를 들어, 특정 조건에 따라 텍스트 색상을 변경하는 등의 작업을 수행할 수 있습니다.

    <!-- 데이터 바인딩 값에 따라 텍스트 색상을 변경하는 예시 -->
    <TextBlock Text="{Binding Status}">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Foreground" Value="Black" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Status}" Value="Complete">
                        <Setter Property="Foreground" Value="Green" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Status}" Value="Pending">
                        <Setter Property="Foreground" Value="Orange" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Status}" Value="Failed">
                        <Setter Property="Foreground" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>

     

    9. MultiBindingConverter

    여러 개의 데이터 바인딩을 처리하는 데 사용되는 Converter입니다. 여러 데이터 소스의 값을 조합하여 하나의 값으로 변환할 수 있습니다. 예를 들어, 두 숫자를 곱하거나, 여러 개의 속성을 결합하여 문자열을 생성하는 등의 작업을 수행할 수 있습니다.

    <!-- 두 값을 곱하는 예시 -->
    <TextBlock>
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource MultiplicationConverter}">
                <Binding Path="Value1" />
                <Binding Path="Value2" />
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>
    public class MultiplicationConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length == 2 && values[0] is double value1 && values[1] is double value2)
            {
                return value1 * value2;
            }
            return Binding.DoNothing;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

     

    10. ImageConverter

    이미지를 다른 형식으로 변환하는 데 사용됩니다. 예를 들어, 이미지를 바이트 배열로 변환하거나, 바이트 배열을 이미지로 변환하는 등의 작업을 수행할 수 있습니다.

    <!-- 이미지를 바이트 배열로 변환하는 예시 -->
    <Window.Resources>
        <local:ImageConverter x:Key="ImageConverter" />
    </Window.Resources>
    <Image Source="{Binding Image, Converter={StaticResource ImageConverter}}" />
    using System;
    using System.Globalization;
    using System.IO;
    using System.Windows.Data;
    using System.Windows.Media.Imaging;
    
    public class ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 입력 값이 BitmapImage인지 확인
            if (value is BitmapImage image)
            {
                // 이미지를 메모리 스트림으로 변환하여 바이트 배열로 가져오기
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    BitmapEncoder encoder = new PngBitmapEncoder(); // PNG 형식으로 인코딩
                    encoder.Frames.Add(BitmapFrame.Create(image)); // 이미지 프레임 추가
                    encoder.Save(memoryStream); // 스트림에 이미지 저장
                    return memoryStream.ToArray(); // 바이트 배열로 변환하여 반환
                }
            }
    
            // 입력 값이 BitmapImage가 아닌 경우 Binding.DoNothing 반환
            return Binding.DoNothing;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 이 컨버터에서는 역변환을 지원하지 않으므로 NotSupportedException 발생
            throw new NotSupportedException();
        }
    }

     

     

    XAML에서 컨버터가 인식이 안 되는 경우

    컨버터 클래스에 MarkupExtension을 추가로 상속하면 됩니다.

     

     

    MarkupExtension

    MarkupExtension은 XAML에서 사용되는 기능 중 하나로, XAML 마크업을 확장하고 커스터마이징하는 데 사용됩니다. MarkupExtension은 System.Windows.Markup 네임스페이스에 정의된 추상 클래스입니다.

    MarkupExtension을 상속하는 클래스를 작성하여 사용자 정의 마크업 확장을 구현할 수 있습니다. 이 확장은 중괄호({}) 안에 특정 구문을 사용하여 XAML에서 값을 생성하거나 변환하는 작업을 수행할 수 있습니다. 예를 들어, 데이터 바인딩 설정, 리소스 참조, 다국어 지원 등 다양한 시나리오에서 MarkupExtension을 사용할 수 있습니다.

    MarkupExtension을 상속한 클래스는 ProvideValue 메서드를 구현해야 합니다. 이 메서드는 XAML에서 확장을 사용할 때 호출되어 해당 확장이 반환해야 할 값을 제공합니다. ProvideValue 메서드에서는 필요한 로직을 수행하여 값을 생성하거나 변환할 수 있습니다.

    사용자는 MarkupExtension을 상속하여 필요한 기능을 구현하고 XAML에서 사용할 수 있습니다. 이를 통해 XAML을 더 동적이고 유연하게 만들 수 있으며, 재사용 가능한 확장을 정의할 수 있습니다.

     

    MarkupExtension 포함 코드 예시

    일반적으로 컨버터를 XAML에서 사용하기 위해서는 컨버터 클래스가 IValueConverter 인터페이스를 구현하면 되지만,  IValueConverter를 구현하는 단독 클래스는 XAML에서 직접적으로 인식되지 않을 수 있습니다. 이는 IValueConverter가 코드 레벨에서 작동하는 .NET Framework 구성 요소이기 때문입니다.

    따라서 MarkupExtension를 상속하는 컨버터를 만들어 XAML에서 사용하면 XAML 런타임이 해당 컨버터를 인식하고 적절하게 처리할 수 있습니다. 

    예를 들어, ValueConverterExtension라는 MarkupExtension를 상속하는 클래스를 작성하고, 해당 클래스를 사용하여 컨버터를 XAML에서 사용할 수 있습니다. 예시는 다음과 같습니다.

    using System;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Markup;
    
    public class ValueConverterExtension : MarkupExtension, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 값을 변환하는 로직을 구현
            // 예: 문자열을 대문자로 변환
            if (value is string str)
            {
                return str.ToUpper();
            }
    
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 변환을 역으로 수행하는 로직을 구현
            // 예: 대문자를 소문자로 변환
            if (value is string str)
            {
                return str.ToLower();
            }
    
            return value;
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this; // 확장 자체를 반환
        }
    }

     

    반응형

    댓글

Designed by Tistory.