두 개의 개별 변환을 통해 데이터 컨텍스트의 속성에 바인딩 된 정수 값을 표시해야하는 상황이 있습니다.
- 범위 내에서 값 반전 (예 : 범위는 1에서 100, 데이터 컨텍스트의 값은 90, 사용자는 10의 값을 봅니다)
- 숫자를 문자열로 변환
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 링크)의 호의로 제가 찾고 있던 것을 정확히 찾았습니다 .
그는 ValueConverterGroup
XAML에서의 사용이 내가 기대했던 것과 정확히 일치 하는 클래스를 정의합니다 . 예를 들면 다음과 같습니다.
<!-- 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
}