programing

XAML에서 여러 값 변환기를 체인으로 연결하는 방법이 있습니까?

oldcodes 2023. 5. 14. 11:03
반응형

XAML에서 여러 값 변환기를 체인으로 연결하는 방법이 있습니까?

두 번의 별도 변환을 거친 후 데이터 컨텍스트의 속성에 바인딩된 정수 값을 표시해야 하는 상황이 발생했습니다.

  1. 범위 내의 값(예: 범위는 1 ~ 100, 데이터 컨텍스트의 값은 90, 사용자 보기 값은 10)을 반대로 표시합니다.
  2. 숫자를 문자열로 변환합니다.

자체 컨버터(IValueConverter 구현)를 만들어 두 단계를 모두 수행할 수 있다는 것을 깨달았습니다.하지만 이미 첫 번째 단계만 수행하는 별도의 값 변환기가 있고 두 번째 단계는 Int32Converter에서 다룹니다.

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

만약 제가 이것들 중 하나라도 명확히 해야 한다면, 저에게 알려주시기 바랍니다.:)

감사해요.

저는 실버라이트 프로젝트에서 개러스 에반스의 방법을 사용했습니다.

제가 구현한 내용은 다음과 같습니다.

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> 

좋은 것들.고마워, 조쉬.:)

Town의 Gareth Evans의 Silverlight 프로젝트 구현은 훌륭하지만 다른 컨버터 매개 변수를 지원하지는 않습니다.

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

변환기:

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은 여기서 구현되지 않습니다. 전체 버전은 Gist를 참조하십시오.

구현:

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

네, 체인 변환기를 연결하는 방법도 있지만 예쁘게 보이지 않고 여기서는 필요 없습니다.만약 여러분이 이것이 필요하게 된다면, 스스로에게 그것이 정말로 옳은 길인지 물어보십시오.변환기를 직접 작성해야 하는 경우에도 항상 단순이 더 잘 작동합니다.

특정한 경우에는 변환된 값을 의 string.property 형식으로 지정하기만 하면 됩니다.Binding여기 당신의 친구입니다.

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

다음은 다중 바인딩을 지원하기 위한 타운의 작은 확장입니다.

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
}

그러나 타운의 대답의 또 다른 확장입니다.특정 요구 사항의 경우 특정 유형의 매개 변수를 전달해야 했지만 Trevi의 답변과 같은 문자열 기반 솔루션은 이를 지원하지 않았습니다.

제 솔루션은 약간의 장황함이 필요하지만 XAML의 사용자로서 우리는 그것에 익숙하지 않습니다;)

public class ValueConverterChainParameters : List<object>
{
    
}

public class ValueConverterChain : List<IValueConverter>, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter is not (null or ValueConverterChainParameters))
        {
            throw new ApplicationException($"{nameof(ValueConverterChain)} parameter must be empty/null or a {nameof(ValueConverterChainParameters)} instance where each element is the parameter to pass to the corresponding converter.");
        }

        ValueConverterChainParameters parameterList = parameter as ValueConverterChainParameters;

        return this
            .Select((converter, index) => (converter, index))
            .Aggregate(value, (currentValue, element) =>
            {
                (IValueConverter converter, int index) = element;
                return converter.Convert(currentValue, targetType, parameterList?[index], culture);
            });
    }

아래 사용량.이 시나리오에서 (내가 아는 바로는 어느 정도 조작된 것으로 알고 있다),MyAngle템플릿으로 작성된 상위 항목에 어떤 이유로 문자열이 있습니다.변경 유형 변환기는 다음과 같습니다.return System.Convert.ChangeType(value, targetType);예되루곳에 Angle 합니다.그런 다음 매개 변수로 곱셈을 수행하는 곱셈 변환기로 전달됩니다.

<RotateTransform >
    <RotateTransform.Angle>
        <Binding Path="MyAngle" RelativeSource="{RelativeSource TemplatedParent}">
            <Binding.Converter>
                <conv:ValueConverterChain>
                    <conv:ChangeTypeConverter/>
                    <conv:MultiplyConverter/>
                </conv:ValueConverterChain>
            </Binding.Converter>
            <Binding.ConverterParameter>
                <conv:ValueConverterChainParameters>
                    <x:Null/>
                    <sys:Int32>-1</sys:Int32>
                </conv:ValueConverterChainParameters>
            </Binding.ConverterParameter>
        </Binding>
    </RotateTransform.Angle>
</RotateTransform>

네, 조금 장황하지만 패스를 지원합니다.null특정 유형의 매개 변수와 전달 매개 변수를 전달하지 않으려는 경우.

언급URL : https://stackoverflow.com/questions/2607490/is-there-a-way-to-chain-multiple-value-converters-in-xaml

반응형