DataBinding 绑定计算表达式 [WPF系列]-DataBinding 绑定计算表达式 XAML内联计算的实现

有哪几种Binding的方式,以及他们之间的区别,我这里就不详细说明了,不知道的可以查查资料。

下面直接举例子来说明吧!~

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

IMultiValueConverter

出处:https://www.cnblogs.com/HQFZ/p/4205304.html

===============================================================

XAML内联计算的实现

一、XAML内联计算

①定义一个类实现IValueConverter接口

②在窗口资源中导入定义的类

<Window.Resources>
    <local:ArithmeticConverter x:Key="converter"></local:ArithmeticConverter>
</Window.Resources>

③使用定义的类实现内联计算,如Storyboard的To属性的设置:

To="{Binding ElementName=window,Path=Width,Converter={StaticResource converter},ConverterParameter=-30}"

二、实例代码演示

①ArithmeticConverter.cs实现IValueConverter接口

using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Data;
 
namespace Animation
{
    public class ArithmeticConverter : IValueConverter
    {
        private const string ArithmeticParseExpression = "([+\-*/]{1,1})\s{0,}(\-?[\d\.]+)";
        private Regex arithmeticRegex = new Regex(ArithmeticParseExpression);
               
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
 
            if (value is double && parameter != null)
            {
                string param = parameter.ToString();
 
                if (param.Length > 0)
                {
                    Match match = arithmeticRegex.Match(param);
                    if (match != null && match.Groups.Count == 3)
                    {
                        string operation = match.Groups[1].Value.Trim();
                        string numericValue = match.Groups[2].Value;
 
                        double number = 0;
                        if (double.TryParse(numericValue, out number)) // this should always succeed or our regex is broken
                        {
                            double valueAsDouble = (double)value;
                            double returnValue = 0;
 
                            switch (operation)
                            {
                                case "+":
                                    returnValue = valueAsDouble + number;
                                    break;
 
                                case "-":
                                    returnValue = valueAsDouble - number;
                                    break;
 
                                case "*":
                                    returnValue = valueAsDouble * number;
                                    break;
 
                                case "/":
                                    returnValue = valueAsDouble / number;
                                    break;
                            }
 
                            return returnValue;
                        }
                    }
                }
            }
 
            return null;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new Exception("The method or operation is not implemented.");
        }
 
    }
}

②内联计算的使用

<Window x:Class="Animation.XamlAnimation"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="XamlAnimation" Height="300" Width="300" Name="window"
    xmlns:local="clr-namespace:Animation"
    >
    <Window.Resources>
        <local:ArithmeticConverter x:Key="converter"></local:ArithmeticConverter>
    </Window.Resources>
    <Button Padding="10" Name="cmdGrow" Height="40" Width="160"
          HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="Width"
                To="{Binding ElementName=window,Path=Width,Converter={StaticResource converter},ConverterParameter=-30}"
                               Duration="0:0:5"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetProperty="Height"
                To="{Binding ElementName=window,Path=Height,Converter={StaticResource converter},ConverterParameter=-50}"
                               Duration="0:0:5"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Button.Triggers>
        <Button.Content>
            Click and Make Me Grow
        </Button.Content>
    </Button>
</Window>

出处:https://blog.csdn.net/songyi160/article/details/54928660

===========================================================================