Преобразователь с несколькими параметрами
Кто-нибудь знает, как использовать конвертер с несколькими параметрами в приложении Windows Phone 7?
Заранее спасибо.
Ответы
Ответ 1
Конвертеры всегда реализуют IValueConverter. Это означает, что вызов Convert или ConvertBack передает один дополнительный параметр. Этот параметр извлекается из XAML.
Как предлагает Hitesh Patel, ничто не мешает вам вводить в параметр более одного значения, если у вас есть разделитель для их разделения позже, , но вы не можете использовать запятую, поскольку она разделяет XAML!
например
XAML
<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
Converter={StaticResource MyConverter},
ConverterParameter=Param1|Param2}" />
конвертер
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
string parameterString = parameter as string;
if (!string.IsNullOrEmpty(parameterString))
{
string[] parameters = parameterString.Split(new char[]{'|'});
// Now do something with the parameters
}
}
Обратите внимание, я не проверял, чтобы увидеть, если pipe "|" символ действителен в XAML (должен быть), но если нет, просто выберите другой символ, который не конфликтует.
Более поздние версии .Net не требуют массива символов для самой простой версии Split
, поэтому вы можете использовать это вместо этого:
string[] parameters = parameterString.Split('|');
Добавление:
Хитрость, которую eBay использовал в URL много лет назад, заключалась в разделении данных в URL с помощью QQ. Двойной Q не встречается в текстовых данных. Если вы когда-нибудь застряли за разделителем текста, который позволит избежать проблем с кодировкой, просто используйте QQ... Это не будет работать с расщеплением (которое требует одиночных символов, но приятно знать) :)
Ответ 2
Вы всегда можете получить класс DependecyObject и добавить столько DependencyProperties, сколько хотите. Например:
ExampleConverter.cs
public class ExampleConverter : DependencyObject, IValueConverter
{
public string Example
{
get => GetValue(ExampleProperty).ToString();
set => SetValue(ExampleProperty, value);
}
public static readonly DependencyProperty ExampleProperty =
DependencyProperty.Register("Example", typeof(string), typeof(ExampleConverter), new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//Do the convert
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
И затем в XAML:
ExampleView.xaml
<ResourceDictionary>
<converters:ExampleConverter x:Key="ExampleConverter" Example="{Binding YourSecondParam}"/>
</ResourceDictionary>
...
<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
Converter={StaticResource ExampleConverter},
ConverterParameter={Binding YourFirstParam}}" />
Ответ 3
Хотя приведенные выше ответы могут быть возможными, они кажутся слишком сложными. Просто используйте IMultiValueConverter
с соответствующим MultiBinding
в коде XAML. Предполагая, что ваша ViewModel имеет свойства FirstValue
, SecondValue
и ThirdValue
, которые соответственно являются int
, double
и string
, допустимый мультиконвертер может выглядеть следующим образом:
С#
public class MyMultiValueConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
int firstValue = (int)values[0];
double secondValue = (double)values[1];
string thirdValue = (string)values[2];
return "You said " + thirdValue + ", but it rather " + firstValue * secondValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException("Going back to what you had isn't supported.");
}
}
XAML
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myNs:MyMultiValueConverter}">
<Binding Path="FirstValue" />
<Binding Path="SecondValue" />
<Binding Path="ThirdValue" />
</MultiBinding>
</TextBlock.Text>
Поскольку для этого не требуется ни метод ProvideValue
, требуемый для MarkupExtension
, ни спецификация DependencyObject
внутри (!) преобразователя, я считаю, что это наиболее элегантное решение.
Ответ 4
Это можно сделать с помощью System.Windows.Markup.MarkupExtension
(документы).
Это позволит вам передавать значения в конвертер, которые можно использовать в качестве аргументов или возвращаемых значений, например:
public class CustomNullToVisibilityConverter : MarkupExtension, IValueConverter
{
public object NullValue { get; set; }
public object NotNullValue { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return NullValue;
return NotNullValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Использование:
...
Visibility="{Binding Property,
Converter={cnv:CustomNullToVisibilityConverter NotNullValue=Visible, NullValue=Collapsed}}"
/>
...
Обязательно укажите пространство имен конвертера в .xaml
.
Ответ 5
Если ваш ввод не будет работать со строкой, и у вас есть несколько параметров (не привязок). Вы можете просто передать коллекцию. Определите любой тип, необходимый для избежания проблем с редактором пользовательского интерфейса с массивами:
public class BrushCollection : Collection<Brush>
{
}
Затем добавьте XAML, используя коллекцию
<TextBox.Background >
<Binding Path="HasInitiativeChanged" Converter="{StaticResource changedToBrushConverter}">
<Binding.ConverterParameter>
<local:BrushCollection>
<SolidColorBrush Color="{DynamicResource ThemeTextBackground}"/>
<SolidColorBrush Color="{DynamicResource SecondaryColorBMedium}"/>
</local:BrushCollection>
</Binding.ConverterParameter>
</Binding>
</TextBox.Background>
А затем приведите результат к массиву соответствующего типа в конвертере:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BrushCollection brushes = (BrushCollection)parameter;