How perform calculation on a XAML Binding value: reverse it, multiply it, subtract from it or add to it?

泪湿孤枕 提交于 2019-12-17 18:33:14

问题


First; the question is rhetorical, I have an answer! I have gotten so much help from looking here that I wanted to give this neat trick back.

Imagine that you have a value that you want to bind to, but it is somehow or somewhat wrong.

  • I had a situation where I wanted to bind to a value, but when the value was 1, I needed 0, and vice-versa.
  • There was a time when I wanted to bind the width of an element to the width of a parent - 68px.

回答1:


Enter the 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;
    }
}

How to use it?

You make a resource for each use in the resource section:

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

The name comes from the function y = a*x + b (Called a "first degree function" in Norwegian), and of course it would be possible to upgrade it to a second degree function y= a*x^2 + bx + c, but I haven't found a use for it yet.

I had a situation where I wanted to make columns based on width. Each time I got 200 pixels more width, I wanted the container to show me another column. At that time I hardcoded a converter, but I should have made a y=(a/x) + b converter instead.

Now, what should I have named this converter so that everybody understand what it is? Since I'm a Norwegian, I used the expression we learned in school, directly translated. Please, if you have a suggestion or an opinion, let me know. Any refinements or improvements you have thought of would also be appreciated...


Maybe "LinearTransformConverter" would better communicate what the converter does for you, I'll think about it. Any other proposals? Tor




回答2:


What is even better is a PolynomialConverter, here's the one-way version:

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

Examples:

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

Alternatively one could use the ConverterParameter instead to not set the Coefficients in the converter itself.

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


来源:https://stackoverflow.com/questions/4969600/how-perform-calculation-on-a-xaml-binding-value-reverse-it-multiply-it-subtra

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!