如何更改绑定值,反转它,乘以,从中减去或添加?

时间:2011-02-11 13:34:49

标签: wpf math binding converter

首先;问题是修辞,我有一个答案!看到这里我得到了很多帮助,我想把这个巧妙的技巧带回来。

想象一下,你有一个你想要绑定的值,但它有点或有些错误。

  • 我有一种情况,我想绑定一个值,但当值为1时,我需要0,反之亦然。
  • 曾经有一段时间我想将元素的宽度绑定到父级的宽度 - 68px。

2 个答案:

答案 0 :(得分:13)

输入 FirstDegreeFunctionConverter

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;

namespace GenericWPF
{
    /// <summary>
    /// Will return a*value + b
    /// </summary>
    public class FirstDegreeFunctionConverter : IValueConverter
    {
        public double A { get; set; }
    public double B { get; set; }

    #region IValueConverter Members

    public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
    {
        double a = GetDoubleValue( parameter, A );

        double x = GetDoubleValue( value, 0.0 );

        return ( a * x ) + B;
    }

    public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
    {
        double a = GetDoubleValue( parameter, A );

        double y = GetDoubleValue( value, 0.0 );

        return ( y - B ) / a;
    }

    #endregion


    private double GetDoubleValue( object parameter, double defaultValue )
    {
        double a;
        if( parameter != null )
            try
            {
                a = System.Convert.ToDouble( parameter );
            }
            catch
            {
                a = defaultValue;
            }
        else
            a = defaultValue;
        return a;
    }
}

如何使用它?

您为资源部分中的每次使用创建资源:

<GenericWPF:FirstDegreeFunctionConverter x:Key="ReverseOne"
                            A="-1"
                            B="1" />

<Border Opacity="{Binding Path=Opacity
    , ElementName=daOtherField
    , Converter={StaticResource ReverseOne}}" />

<GenericWPF:FirstDegreeFunctionConverter x:Key="ListboxItemWidthToErrorWidth"
     A="1"
     B="-68" />

<TextBox MaxWidth="{Binding Path=ActualWidth
   , Converter={StaticResource ListboxItemWidthToErrorWidth}
   , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />

该名称来自函数y = a * x + b(在挪威语中称为“第一度函数”),当然可以将其升级为二次函数y = a * x ^ 2 + bx + c,但我还没有找到用途。

我有一种情况,我想根据宽度制作列。每次我有200像素的宽度,我希望容器向我显示另一列。那时我硬编码了一个转换器,但我应该改为使用y =(a / x)+ b转换器。

现在,我应该将这个转换器命名为什么,以便每个人都能理解它是什么?由于我是挪威人,我使用了我们在学校学到的表达,直接翻译。如果您有任何建议或意见,请告诉我。 您所想到的任何改进或改进也将受到赞赏......


也许“ LinearTransformConverter ”会更好地传达转换器为您做的事情,我会考虑一下。 还有其他建议吗? TOR

答案 1 :(得分:6)

更好的是PolynomialConverter,这是单向版本:

public class PolynomialConverter : IValueConverter
{
    public DoubleCollection Coefficients { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double x = (double)value;
        double output = 0;
        for (int i = Coefficients.Count - 1; i >= 0 ; i--)
            output += Coefficients[i] * Math.Pow(x, (Coefficients.Count - 1) - i);

        return output;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //This one is a bit tricky, if anyone feels like implementing this...
        throw new NotSupportedException();
    }
}

示例:

<!-- x^2 -->
<vc:PolynomialConverter Coefficients="1,0,0"/>
<!-- x + 5 -->
<vc:PolynomialConverter Coefficients="1,5"/>
<!-- 2x + 4 -->
<vc:PolynomialConverter Coefficients="2,4"/>

或者可以使用ConverterParameter而不是在转换器本身中设置系数。

DoubleCollection coefficients = DoubleCollection.Parse((string)parameter);
//...