数据库可以定义表不同列之间的计算公式,进行自动公式计算,但如何实现行上的动态公式计算呢?行由于可以动态扩展,在某些应用场景下将能很好的解决实际问题。

1、VS2012新建一个WPF应用程序WpfApp_DynCalc,并添加一个类DynCalc.cs,如下图:

2、编辑MainWindow.xaml,代码如下:

 <Window x:Class="WpfApp_DynCalc.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF动态计算示例" Height="350" Width="525">
<Grid>
<Grid.Resources>
<Style TargetType="DataGrid">
<!--网格线颜色-->
<Setter Property="CanUserResizeColumns" Value="false"/>
<Setter Property="Background" Value="#E6DBBB" />
<Setter Property="BorderBrush" Value="#d6c79b" />
<Setter Property="HorizontalGridLinesBrush">
<Setter.Value>
<SolidColorBrush Color="#d6c79b"/>
</Setter.Value>
</Setter>
<Setter Property="VerticalGridLinesBrush">
<Setter.Value>
<SolidColorBrush Color="#d6c79b"/>
</Setter.Value>
</Setter>
</Style> <!--标题栏样式-->
<!--<Style TargetType="DataGridColumnHeader" >
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="30"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="Background" Value="White" />
<Setter Property="FontWeight" Value="Bold"/>
</Style>--> <Style TargetType="DataGridColumnHeader">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="28" />
<Setter Property="Foreground" Value="#323433" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1"
BorderBrush="#e6dbba"
Width="Auto">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Path x:Name="SortArrow" Visibility="Collapsed" Data="M0,0 L1,0 0.5,1 z" Stretch="Fill" Grid.Column="2" Width="8" Height="6" Fill="White" Margin="0,0,50,0"
VerticalAlignment="Center" RenderTransformOrigin="1,1" />
<Rectangle Width="1" Fill="#d6c79b" HorizontalAlignment="Right" Grid.ColumnSpan="1" />
<!--<TextBlock Background="Red">
<ContentPresenter></ContentPresenter></TextBlock>-->
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="25"/>
</Style>
<!--行样式触发-->
<!--背景色改变必须先设置cellStyle 因为cellStyle会覆盖rowStyle样式-->
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="#F2F2F2" />
<Setter Property="Height" Value="25"/>
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<!--隔行换色-->
<Trigger Property="AlternationIndex" Value="0" >
<Setter Property="Background" Value="#e7e7e7" />
</Trigger>
<Trigger Property="AlternationIndex" Value="1" >
<Setter Property="Background" Value="#f2f2f2" />
</Trigger> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"/>
<!--<Setter Property="Foreground" Value="White"/>-->
</Trigger> <Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style> <!--单元格样式触发-->
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<TextBlock TextAlignment="Center" VerticalAlignment="Center" >
<ContentPresenter />
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>-->
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources> <DataGrid Name="dgrid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="256" Width="498" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="指标" Binding="{Binding Zb}" Width="118"/>
<DataGridTextColumn Header="值" Binding="{Binding Value}" Width="100"/>
<DataGridTextColumn Header="公式" Binding="{Binding Formula}" Width="188"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="计 算" HorizontalAlignment="Left" Margin="419,281,0,0" VerticalAlignment="Top" Width="85" Click="Button_Click_1" Height="28" />
<TextBlock Name="lblResult" HorizontalAlignment="Left" Margin="28,281,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/> </Grid>
</Window>

3、编辑后台文件MainWindow.xaml.cs,代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; using System.Collections.ObjectModel;
namespace WpfApp_DynCalc
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); ObservableCollection<Dynformula> ofs = new ObservableCollection<Dynformula>();
ofs.Add(new Dynformula { Zb = "A", Value = "", Formula = "" });
ofs.Add(new Dynformula { Zb = "B", Value = "", Formula = "2*A+1" });
ofs.Add(new Dynformula { Zb = "C", Value = "", Formula = "B*B" });
ofs.Add(new Dynformula { Zb = "D", Value = "", Formula = "C-2" });
ofs.Add(new Dynformula { Zb = "Z", Value = "", Formula = "D+C" });
this.dgrid.ItemsSource = ofs; } private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.lblResult.Text = "计算...";
this.dgrid.ItemsSource= DynCalc.CalcScript(ref this.dgrid);
this.lblResult.Text = "计算完成!"; }
} public class Dynformula
{
private string zb; public string Zb
{
get { return zb; }
set { zb = value; }
}
private string value; public string Value
{
get { return this.value; }
set { this.value = value; }
}
private string formula; public string Formula
{
get { return formula; }
set { formula = value; }
} }
}

3、编辑类DynCalc.cs,代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace WpfApp_DynCalc
{
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Reflection;
using System.Globalization;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
public static class DynCalc
{ public static ObservableCollection<Dynformula> CalcScript(ref DataGrid dgrid)
{ CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
CompilerParameters objCompilerParameters = new CompilerParameters();
objCompilerParameters.ReferencedAssemblies.Add("System.dll");
objCompilerParameters.GenerateExecutable = false;
objCompilerParameters.GenerateInMemory = true;
CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode(ref dgrid));
if (cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach (CompilerError err in cr.Errors)
{
Console.WriteLine(err.ErrorText);
}
return null;
}
else
{
// 通过反射,调用实例
Assembly objAssembly = cr.CompiledAssembly;
object objDynCalc = objAssembly.CreateInstance("DynamicCodeGenerate.RunScript");
//MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
//Console.WriteLine(objMI.Invoke(objHelloWorld, null)); ObservableCollection<Dynformula> ofsnew = new ObservableCollection<Dynformula>();
//循环datagrid进行公式计算并赋值
for (int i = ; i < dgrid.Items.Count; i++)
{
Dynformula item = dgrid.Items[i] as Dynformula;
if (item == null)
{
break;
}
string zb = item.Zb;
PropertyInfo pinfo = objDynCalc.GetType().GetProperty(zb);
if (pinfo != null && pinfo.CanRead) {
//获取属性get值
object obj_Name = pinfo.GetValue(objDynCalc, null);
// item.Value = obj_Name.ToString();
ofsnew.Add(new Dynformula { Zb = item.Zb, Value = obj_Name.ToString(), Formula = item.Formula});
}
}
return ofsnew;
}
}
/// <summary>
/// 计算逻辑C#脚本动态构建
/// </summary>
/// <param name="dgrid">存有指标以及指标计算公式的datagrid</param>
/// <returns>C#脚本</returns>
static string GenerateCode(ref DataGrid dgrid)
{
StringBuilder sb = new StringBuilder();
StringBuilder sb构建函数内容 = new StringBuilder();
sb.Append("using System;");
sb.Append(Environment.NewLine);
sb.Append("namespace DynamicCodeGenerate");
sb.Append(Environment.NewLine);
sb.Append("{");
sb.Append(Environment.NewLine);
sb.Append(" public class RunScript");
sb.Append(Environment.NewLine);
sb.Append(" {");
//------------------------------------------------------------
for(int i=;i<dgrid.Items.Count;i++)
{
Dynformula item = dgrid.Items[i] as Dynformula;
if (item == null)
{
break;
}
string zb = item.Zb;
sb.Append(Environment.NewLine);
sb.AppendFormat(" public double _{0};", item.Zb);
sb.Append(Environment.NewLine);
sb.AppendFormat(" public double {0}",item.Zb);
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine); if (item.Formula.Trim() != "")
{
sb.Append(" set{ "+item.Zb+"=value;}" );
sb.Append(Environment.NewLine);
sb.Append(" get{return "+ item.Formula + ";}");
}
else
{
sb.Append(" set{ _" + item.Zb + "=value;}");
sb.Append(Environment.NewLine);
sb.Append(" get{return _"+item.Zb+";} ");
sb.Append(Environment.NewLine);
sb构建函数内容.Append(" _" + item.Zb + "=" + item.Value);
}
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
}
//--------------------------------------------
//构造函数进行赋值
sb.Append(Environment.NewLine);
sb.Append(" public RunScript()");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.AppendFormat(" {0};",sb构建函数内容.ToString());
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine); //----------------------------------------------
sb.Append(Environment.NewLine);
sb.Append(" public string OutPut()");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.Append(" return \"Hello world!\";");
sb.Append(Environment.NewLine);
sb.Append(" }");
//-----------------------------------------
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
sb.Append("}"); string code = sb.ToString();
Console.WriteLine(code);
return code;
} }
}

4、运行程序,其中值列的值为初始值,点击计算后会根据公式列配置进行动态计算,初始化界面如下:

5、点击计算后界面如下:

可见现在的值是根据公式配置进行动态计算的。当然代码经过扩展还可以支持函数和简单的逻辑判断,如if ...else等。实现更强大的逻辑处理。

WPF实现强大的动态公式计算的更多相关文章

  1. 【Windows 10 应用开发】使用x:Bind标记动态获得计算结果

    UWP 在传统(WPF)的Binding标记上引入了 Bind 标记,Bind 基于编译阶段生成,因而具有较高的性能.但是,你得注意,这个性能上的优化是免去了运行阶段动态绑定的开销,这是不包括数据源的 ...

  2. [转]EXCEL如何使用动态公式

    本文转自:http://tech.cncms.com/ruanjian/office/excel/95440.html 也许大家可能还不知道Excel中的动态公式是什么,所谓的动态公式,不是普通的公式 ...

  3. WPF重写Image实现动态图片--未测试

    WPF很强大,但是当WPF的image控件遇到gif时就只读了图片的第一帧,很好很强大! WPF不屑于gif的简单动画! 幸好WPF里有MediaElement这个东西,它是对MediaPlyer的一 ...

  4. 用python实现计算1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))类似的公式计算

    作业需求: 开发一个简单的python计算器 1.实现加减乘除及拓号优先级解析 2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 ...

  5. 深入浅出Mybatis系列(九)---强大的动态SQL

    上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis ...

  6. 使用Machin公式计算

    使用Machin公式计算,并使用百亿进制+末项位数控制,这里可算出数万位(比最简PI快80倍),源代码约40行,在本网页中. 计算公式 PI=16arctg(1/5)-4arctg(1/239),其中 ...

  7. c语言详解  蔡勒(Zeller)公式计算某一天是星期几  极其方便

    —— 蔡勒(Zeller)公式 ,小于等于14,即在蔡勒公式中,某年的1.2月要看作上一年的13.14月来计算,比如2003年1月1日要看作2002年的13月1日来计算):d:日:[ ]代表取整,即只 ...

  8. C#动态表达式计算

    C#动态表达式计算 应该有不少人开发过程中遇到过这样的需求,我们直接看图说话: 如上图所示,其中Entity为实体类,其中包括五个属性,该五个属性的值分别来自于数据库查询结果: 用户通过可视化界面进行 ...

  9. C#动态表达式计算(续2)

    上两篇废话太多,这一次我就不多说了,由于代码比较简单,可以直接从https://github.com/scottshare/DynamicExpress.git地址下载. 以下说明一下使用方法: Dy ...

随机推荐

  1. photoshop学习目录

    前面的话 前端工程师最基本的工作是切图.photoshop用的6不6,对于工作效率有很大的影响.小火柴将前端工程师需要掌握的photoshop的知识和技能进行了梳理和归纳,总结成以下目录 目录 前端工 ...

  2. Android线程之Looper

    之前已经为大家奉献了关于Handler和Message的使用,本篇我们来了解一下Handler内部的具体使用,本篇主要探讨Looper的在处理Handler的消息机制中起的重要作用,我们知道我们在子线 ...

  3. android target unknown and state offline解决办法

    没有错,将adb的版本升级一下就好了! 下载地址为:http://files.cnblogs.com/files/hujunzheng/adb1.0.32.zip

  4. 微信小程序中rpx与rem单位使用

    原作者: 小小小   来自: 授权地址 本文讲解rpx和rem应用于微信小程序,如果你还没有入门,建议先从下面看起: 微信小程序官方文档web app变革之remrpx单位官方文档rpx单位基础介绍 ...

  5. android之数据存储之SQLite

    SQLite开源轻量级数据库,支持92-SQL标准,主要用于嵌入式系统,只占几百K系统资源此外,SQLite 不支持一些标准的 SQL 功能,特别是外键约束(FOREIGN KEY constrain ...

  6. Android中自定义属性(attrs.xml,TypedArray的使用)

    做Android布局是件很享受的事,这得益于他良好的xml方式.使用xml可以快速有效的为软件定义界面.可是有时候我们总感觉官方定义的一些基本组件不够用,自定义组件就不可避免了.那么如何才能做到像官方 ...

  7. Mybatis在idea中错误:Invalid bound statement (not found)

    学习mybatis的过程中,测试mapper自动代理的时候一直出错,在eclipse中可以正常运行,而同样的代码在idea中却无法成功.虽然可以继续调试,但心里总是纠结原因.百度了好久,终于找到一个合 ...

  8. JS根据身份证号码算年龄

    如果把身份证号码传到页面上,在前端页面获取年龄就需要用到JS脚本了: function GetAge(identityCard) { var len = (identityCard + "& ...

  9. Elasticsearch增删改查 之 —— Update更新

    更新操作,一般用这个的,应该不会很多吧!ES本身还是一个倾向于查询检索的框架,对于这种更新的操作,太过频繁总归是不好的. 不过阅读本篇后,你可以使用Script对所有的文档执行更新操作,也可以使用do ...

  10. jquery基础知识汇总

    jquery基础知识汇总 一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库.源码戳这 jQu ...