首页 > 代码库 > [WPF系列]-DataBinding 绑定计算表达式

[WPF系列]-DataBinding 绑定计算表达式

 

 

 

 

Width="{Binding  RelativeSource={RelativeSource Self}, Path=ActualWidth,Converter={StaticResource MathConverter},ConverterParameter=(@VALUE-100.0)}"

 

Width="{Binding ElementName=RootWindow, Path=ActualWidth,Converter={StaticResource MathConverter},ConverterParameter=((@VALUE-200)*.3)}"

 

 

// Does a math equation on the bound value.// Use @VALUE in your mathEquation as a substitute for bound value// Operator order is parenthesis first, then Left-To-Right (no operator precedence)public class MathConverter : IValueConverter{    private static readonly char[] _allOperators = new[] { +, -, *, /, %, (, ) };     private static readonly List<string> _grouping = new List<string> { "(", ")" };    private static readonly List<string> _operators = new List<string> { "+", "-", "*", "/", "%" };     #region IValueConverter Members     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)    {        // Parse value into equation and remove spaces        var mathEquation = parameter as string;        mathEquation = mathEquation.Replace(" ", "");        mathEquation = mathEquation.Replace("@VALUE", value.ToString());         // Validate values and get list of numbers in equation        var numbers = new List<double>();        double tmp;         foreach (string s in mathEquation.Split(_allOperators))        {            if (s != string.Empty)            {                if (double.TryParse(s, out tmp))                {                    numbers.Add(tmp);                }                else                {                    // Handle Error - Some non-numeric, operator, or grouping character found in string                    throw new InvalidCastException();                }            }        }         // Begin parsing method        EvaluateMathString(ref mathEquation, ref numbers, 0);         // After parsing the numbers list should only have one value - the total        return numbers[0];    }     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)    {        throw new NotImplementedException();    }     #endregion     // Evaluates a mathematical string and keeps track of the results in a List<double> of numbers    private void EvaluateMathString(ref string mathEquation, ref List<double> numbers, int index)    {        // Loop through each mathemtaical token in the equation        string token = GetNextToken(mathEquation);         while (token != string.Empty)        {            // Remove token from mathEquation            mathEquation = mathEquation.Remove(0, token.Length);             // If token is a grouping character, it affects program flow            if (_grouping.Contains(token))            {                switch (token)                {                    case "(":                        EvaluateMathString(ref mathEquation, ref numbers, index);                        break;                     case ")":                        return;                }            }             // If token is an operator, do requested operation            if (_operators.Contains(token))            {                // If next token after operator is a parenthesis, call method recursively                string nextToken = GetNextToken(mathEquation);                if (nextToken == "(")                {                    EvaluateMathString(ref mathEquation, ref numbers, index + 1);                }                 // Verify that enough numbers exist in the List<double> to complete the operation                // and that the next token is either the number expected, or it was a ( meaning                // that this was called recursively and that the number changed                if (numbers.Count > (index + 1) &&                    (double.Parse(nextToken) == numbers[index + 1] || nextToken == "("))                {                    switch (token)                    {                        case "+":                            numbers[index] = numbers[index] + numbers[index + 1];                            break;                        case "-":                            numbers[index] = numbers[index] - numbers[index + 1];                            break;                        case "*":                            numbers[index] = numbers[index] * numbers[index + 1];                            break;                        case "/":                            numbers[index] = numbers[index] / numbers[index + 1];                            break;                        case "%":                            numbers[index] = numbers[index] % numbers[index + 1];                            break;                    }                    numbers.RemoveAt(index + 1);                }                else                {                    // Handle Error - Next token is not the expected number                    throw new FormatException("Next token is not the expected number");                }            }             token = GetNextToken(mathEquation);        }    }     // Gets the next mathematical token in the equation    private string GetNextToken(string mathEquation)    {        // If we‘re at the end of the equation, return string.empty        if (mathEquation == string.Empty)        {            return string.Empty;        }         // Get next operator or numeric value in equation and return it        string tmp = "";        foreach (char c in mathEquation)        {            if (_allOperators.Contains(c))            {                return (tmp == "" ? c.ToString() : tmp);            }            else            {                tmp += c;            }        }         return tmp;    }}

 

参考

 

MathConverter - How to Do Math in XAML

the-math-converter

[WPF系列]-DataBinding 绑定计算表达式