[wpf] XAML에서 여러 값 변환기를 연결하는 방법이 있습니까?

두 개의 개별 변환을 통해 데이터 컨텍스트의 속성에 바인딩 된 정수 값을 표시해야하는 상황이 있습니다.

  1. 범위 내에서 값 반전 (예 : 범위는 1에서 100, 데이터 컨텍스트의 값은 90, 사용자는 10의 값을 봅니다)
  2. 숫자를 문자열로 변환

IValueConverter를 구현하는 자체 변환기를 만들어 두 단계를 모두 수행 할 수 있다는 것을 알고 있습니다. 그러나 이미 첫 번째 단계 만 수행하는 별도의 값 변환기가 있으며 두 번째 단계는 Int32Converter에서 다룹니다.

이 두 개의 기존 클래스를 집계하는 추가 클래스를 만들지 않고도 XAML에서 연결할 수있는 방법이 있습니까?

이에 대해 명확히해야하는 경우 알려 주시기 바랍니다. 🙂

감사.



답변

Silverlight 프로젝트에서 Gareth Evans 가이 방법 을 사용 했습니다 .

내 구현은 다음과 같습니다.

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

다음과 같이 XAML에서 사용할 수 있습니다.

<c:ValueConverterGroup x:Key="InvertAndVisibilitate">
   <c:BooleanInverterConverter/>
   <c:BooleanToVisibilityConverter/>
</c:ValueConverterGroup>


답변

Josh Smith : Piping Value Converters (archive.org 링크)의 호의로 제가 찾고 있던 것을 정확히 찾았습니다 .

그는 ValueConverterGroupXAML에서의 사용이 내가 기대했던 것과 정확히 일치 하는 클래스를 정의합니다 . 예를 들면 다음과 같습니다.

<!-- Converts the Status attribute text to a SolidColorBrush used to draw
     the output of statusDisplayNameGroup. -->
<local:ValueConverterGroup x:Key="statusForegroundGroup">
  <local:IntegerStringToProcessingStateConverter  />
  <local:ProcessingStateToColorConverter />
  <local:ColorToSolidColorBrushConverter />
</local:ValueConverterGroup> 

좋은 물건. 고마워, 조쉬. 🙂


답변

Gareth Evans의 Silverlight 프로젝트에 대한 Town의 구현 은 훌륭하지만 다른 변환기 매개 변수를 지원하지 않습니다.

매개 변수를 쉼표로 구분하여 제공 할 수 있도록 수정했습니다 (물론 이스케이프하지 않는 한).

변환기:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    private string[] _parameters;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(parameter != null)
            _parameters = Regex.Split(parameter.ToString(), @"(?<!\\),");

        return (this).Aggregate(value, (current, converter) => converter.Convert(current, targetType, GetParameter(converter), culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private string GetParameter(IValueConverter converter)
    {
        if (_parameters == null)
            return null;

        var index = IndexOf(converter as IValueConverter);
        string parameter;

        try
        {
            parameter = _parameters[index];
        }

        catch (IndexOutOfRangeException ex)
        {
            parameter = null;
        }

        if (parameter != null)
            parameter = Regex.Unescape(parameter);

        return parameter;
    }
}

참고 : ConvertBack은 여기에서 구현되지 않습니다 . 정식 버전 은 내 요점 을 참조하십시오 .

이행:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:ATXF.Converters;assembly=ATXF" x:Class="ATXF.TestPage">
  <ResourceDictionary>
    <converters:ValueConverterGroup x:Key="converters">
      <converters:ConverterOne />
      <converters:ConverterTwo />
    </converters:ValueConverterGroup>
  </ResourceDictionary>

  <Label Text="{Binding InitialValue, Converter={StaticResource converters}, ConverterParameter='Parameter1,Parameter2'}" />
</ContentPage>


답변

예, 변환기를 연결하는 방법이 있지만 예쁘지 않고 여기에 필요하지 않습니다. 이것을 필요로한다면, 그것이 정말로 갈 길이 냐고 자문 해보십시오. 단순 변환기를 직접 작성해야하는 경우에도 항상 더 잘 작동합니다.

특정 경우에는 변환 된 값을 문자열로 형식화하기 만하면됩니다. StringFormat속성 Binding은 여기 에있는 당신의 친구입니다.

 <TextBlock Text="{Binding Value,Converter={StaticResource myConverter},StringFormat=D}" />


답변

다음은 다중 바인딩을 지원하기 위해 Town의 답변 을 확장 한 것입니다 .

public class ValueConverterGroup : List<IValueConverter>, IValueConverter, IMultiValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return Convert(values as object, targetType, parameter, culture);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}


답변