zoukankan      html  css  js  c++  java
  • DataBinding 绑定计算表达式

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

    有哪几种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

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

  • 相关阅读:
    从与计算机结缘说起
    个人作业2:APP案例分析
    团队作业4——第一次项目冲刺(Alpha版本)第二篇
    团队项目作业1团队展示与选题
    团队作业4——第一次项目冲刺(Alpha版本)第三篇
    团队作业3——需求改进&系统设计
    技术博客
    技术博客二
    bootstrap前端框架使用总结分享
    ADO.NET Entities Framework 的增删查改(我自己写的,可以作为范例)
  • 原文地址:https://www.cnblogs.com/mq0036/p/12543393.html
Copyright © 2011-2022 走看看