如何在 Windows Phone 7 应用程序中使用具有多个参数的转换器?
7 回答
转换器总是实现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
}
}
注意,我还没有检查它是否有管道“|” 字符在 XAML 中有效(应该是),但如果不选择另一个不冲突的字符。
更高版本的 .Net 最简单版本不需要字符数组Split
,因此您可以改用它:
string[] parameters = parameterString.Split('|');
附录:
多年前,eBay 在 url 中使用的一个技巧是用 QQ 分隔 URL 中的数据。文本数据中自然不会出现双 Q。如果您遇到一个可以避免编码问题的文本分隔符,请使用 QQ……这不适用于拆分(它需要单个字符,但很高兴知道):)
虽然上述答案可能是可行的,但它们似乎过于复杂。只需在 XAML 代码中使用IMultiValueConverter
适当的 an即可。MultiBinding
假设您的 ViewModel 具有属性FirstValue
、SecondValue
和ThirdValue
,它们分别是 an int
、 adouble
和 a string
,一个有效的多转换器可能如下所示:
C#
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's 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
内部(!)转换器的规范,我相信这是最优雅的解决方案。
您始终可以从DependecyObject
类派生并添加任意数量的 DependencyProperty
对象。例如:
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}}" />
这可以使用System.Windows.Markup.MarkupExtension
( docs ) 来完成。
这将允许您将值传递给可用作参数或返回值的转换器,例如:
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
.
与 Kyle Olson 的回答类似,您可以像这样使用 Specialized Collection:
XAML 文件:
xmlns:specialized="clr-namespace:System.Collections.Specialized;assembly=System"
<local:BoolToMessage x:Key="BoolToMessage"/>
<Label
>
<Label.Content>
<Binding ElementName="mainWin" Path="HasSeedFile"
FallbackValue="False" Converter="{StaticResource BoolToMessage}"
Mode="OneWay">
<Binding.ConverterParameter>
<specialized:StringCollection>
<sys:String>param1</sys:String>
<sys:String>param2</sys:String>
</specialized:StringCollection>
</Binding.ConverterParameter>
</Binding>
</Label.Content>
</Label>
转换器:
using System.Collections.Specialized;
[ValueConversion(typeof(bool), typeof(string))]
public class BoolToMessage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string[] p = new string[((StringCollection) parameter).Count];
((StringCollection) parameter).CopyTo(p,0);
return (bool) value ? p[0] : p[1];
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
有几种专业集合类型可以满足大多数需求。
Xamarin 的解决方案:
public class BoolStateConverter : BindableObject, IValueConverter, IMarkupExtension
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var boolValue = (bool)value;
return boolValue ? EnabledValue : DisabledValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public static BindableProperty EnabledValueProperty = BindableHelper.CreateProperty<string>(nameof(EnabledValue));
public string EnabledValue
{
get => (string)GetValue(EnabledValueProperty);
set => SetValue(EnabledValueProperty, value);
}
public static BindableProperty DisabledValueProperty = BindableHelper.CreateProperty<string>(nameof(DisabledValue));
public string DisabledValue
{
get => (string)GetValue(DisabledValueProperty);
set => SetValue(DisabledValueProperty, value);
}
}
XAML 消耗:
<ContentPage.Resources>
<ResourceDictionary>
<converters:BoolStateConverter
x:Key="BackwardButtonConverter"
EnabledValue="{x:Static res:Images.IcActiveButton}"
DisabledValue="{x:Static res:Images.IcInactiveButton}" />
</ResourceDictionary>
</ContentPage.Resources>
如果您的输入不适用于字符串,并且您有多个参数(不是绑定)。你可以只传递一个集合。定义需要的任何类型之一以避免数组的一些 UI 编辑器问题:
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;