C# 多参数转换器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11323169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 17:24:39  来源:igfitidea点击:

Converter With Multiple Parameters

c#silverlightwindows-phone-7xamlivalueconverter

提问by Harshad Bhola

How does one use a converter with Multiple parameters in a Windows Phone 7 Application?

如何在 Windows Phone 7 应用程序中使用具有多个参数的转换器?

采纳答案by Gone Coding

Converters always implement IValueConverter. That means a call to Convertor ConvertBackpasses a single additional parameter. That parameter is extracted from the XAML.

转换器总是实现IValueConverter。这意味着对ConvertConvertBack的调用会传递一个附加参数。该参数是从 XAML 中提取的。

As Hitesh Patel suggests there is nothing to stop you putting more than one value into the parameter, so long as you have a delimiter to separate them out later, but you cannot use a comma as that delimits the XAML!

正如 Hitesh Patel 所建议的,没有什么可以阻止您将多个值放入参数中,只要您稍后有一个分隔符将它们分开,但是您不能使用逗号作为 XAML的分隔符

e.g.

例如

XAML

XAML

<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
                        Converter={StaticResource MyConverter}, 
                        ConverterParameter=Param1|Param2}" />

Converter

转换器

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

Note, I have not checked it to see if a Pipe "|" character is valid in XAML there (should be), but if not just choose another character that does not clash.

注意,我没有检查它是否有管道“|” 字符在 XAML 中有效(应该是),但如果不是,则选择另一个不冲突的字符。

Later versions of .Net do not require a character array for the simplest version of Split, so you can use this instead:

.Net 的最新版本不需要最简单版本的字符数组Split,因此您可以使用它:

string[] parameters = parameterString.Split('|');

Addendum:

附录:

A trick eBay used to use in urls, years ago, was to delimit data in the URL with QQ. A double-Q does not naturally occur in text data. If you ever get stuck for a text delimiter that will avoid encoding issues just use QQ... This will not work with split though (which requires single characters, but nice to know) :)

多年前,eBay 在 URL 中使用的一个技巧是用 QQ 分隔 URL 中的数据。双 Q 不会自然出现在文本数据中。如果您遇到了可以避免编码问题的文本分隔符,请使用 QQ ......虽然这不适用于 split(它需要单个字符,但很高兴知道):)

回答by Kamil Stadryniak

You can always derive from DependecyObjectclass and add as many DependencyPropertyobjects as you want. For example:

您始终可以从DependecyObject类派生并添加 任意数量的DependencyProperty对象。例如:

ExampleConverter.cs

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();
    }
}

And then in XAML:

然后在 XAML 中:

ExampleView.xaml

示例视图.xaml

<ResourceDictionary>
    <converters:ExampleConverter x:Key="ExampleConverter" Example="{Binding YourSecondParam}"/>
</ResourceDictionary>
...
<TextBlock Text="{Binding Path=ReleaseDate, Mode=OneWay,
                    Converter={StaticResource ExampleConverter}, 
                    ConverterParameter={Binding YourFirstParam}}" />

回答by Alfie

This can be done using System.Windows.Markup.MarkupExtension(docs).

这可以使用System.Windows.Markup.MarkupExtension( docs)来完成。

This will allow you pass values to the converter which could be used as arguments or return values, for example:

这将允许您将值传递给转换器,这些值可以用作参数或返回值,例如:

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();
    }
}

Usage:

用法:

...
Visibility="{Binding Property, 
 Converter={cnv:CustomNullToVisibilityConverter NotNullValue=Visible, NullValue=Collapsed}}" 
/>
...

Be sure to reference the namespace of the converter in the .xaml.

请务必在 .xml 文件中引用转换器的命名空间.xaml

回答by Informagic

While the above answers may be feasible, they seem to be overly complicated. Simply use an IMultiValueConverterwith an appropriate MultiBindingin the XAML code. Assuming that your ViewModel has the properties FirstValue, SecondValue, and ThirdValue, which are an int, a double, and a string, respectively, a valid multi converter might look like this:

虽然上述答案可能是可行的,但它们似乎过于复杂。只需在 XAML 代码中使用IMultiValueConverter合适MultiBinding的 。假设您的 ViewModel 具有属性FirstValueSecondValueThirdValue,分别是 an int、 adouble和 a string,有效的多转换器可能如下所示:

C#

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

XAML

<TextBlock.Text>
  <MultiBinding Converter="{StaticResource myNs:MyMultiValueConverter}">
    <Binding Path="FirstValue" />
    <Binding Path="SecondValue" />
    <Binding Path="ThirdValue" />
  </MultiBinding>
</TextBlock.Text>

Since it requires neither fumbling with the ProvideValuemethod required by MarkupExtension, nor the specification of a DependencyObjectinside(!) a converter, I do believe that this is the most elegant solution.

由于它既不需要摸索ProvideValue所需的方法MarkupExtension,也不需要DependencyObject内部(!)转换器的规范,我相信这是最优雅的解决方案。

回答by Kyle Olson

If your input will not work with a string, and you have multiple parameters (not bindings). You can just pass an collection. Define one of whatever type is needed to avoid some UI Editor issues with arrays:

如果您的输入不适用于字符串,并且您有多个参数(不是绑定)。你可以只传递一个集合。定义需要的任何类型之一,以避免数组的一些 UI 编辑器问题:

public class BrushCollection : Collection<Brush>
{
}

Then add the XAML using the collection

然后使用集合添加 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>

And then cast the result to an array of the appropriate type in the converter:

然后将结果转换为转换器中适当类型的数组:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        BrushCollection brushes = (BrushCollection)parameter;

回答by mr5

Solution for Xamarin:

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

XAML 消耗:

<ContentPage.Resources>
    <ResourceDictionary>
        <converters:BoolStateConverter
            x:Key="BackwardButtonConverter"
            EnabledValue="{x:Static res:Images.IcActiveButton}"
            DisabledValue="{x:Static res:Images.IcInactiveButton}" />
    </ResourceDictionary>
</ContentPage.Resources>