C# 如何纯粹从codebehind创建动态内存ASP.NET图表?
我正在ASP.NET应用程序中使用C# 如何纯粹从codebehind创建动态内存ASP.NET图表?,c#,asp.net,charts,C#,Asp.net,Charts,我正在ASP.NET应用程序中使用System.Web.UI.DataVisualization.Charting 4.0。因此,它在某些环境下工作良好: var chart = new Chart(); // Define the chart area Grid grid = new Grid(); ChartArea chartArea = new ChartArea(); [... setting lots of chartArea properties here...] ChartA
System.Web.UI.DataVisualization.Charting 4.0
。因此,它在某些环境下工作良好:
var chart = new Chart();
// Define the chart area
Grid grid = new Grid();
ChartArea chartArea = new ChartArea();
[... setting lots of chartArea properties here...]
ChartArea3DStyle areaStyle = new ChartArea3DStyle(chartArea);
chart.ChartAreas.Add(chartArea);
[... more ...]
[... build Series, Legends, etc here ...]
chart.SaveImage("c:\fakepath\myreport.png", ChartImageFormat.Png);
我省略了95%的用于构建图表的代码(非常复杂的逻辑,通过复杂的数据结构进行大量循环),然后将其保存到磁盘,并从aspx页面呈现如下:
<img src="http://fakeserver/fakepath/myreport.png">
在某些客户环境中,这种方法不起作用,因为IIS进程没有写入本地磁盘的权限,而且他们不想打开本地磁盘。此外,当多个用户查看(并生成)图表时,它的可伸缩性不是很强,每个用户的图表都会有所不同
如何在内存中生成此图表?
我一直在看这个类,但找不到相关的代码示例。理想的情况是,如果我可以完全按照上面所示构建图表,而不是保存到磁盘,我可以将图表存储在内存中(缓存?会话?),这样我就可以将aspx页面中的
标记指向内存中的数据,图像将呈现在页面上。我不想求助于声明式aspx图表构建,因为逻辑太复杂,需要全部用c#代码完成。我也不能使用任何将图表图像写入磁盘的方法
它是如何完成的?我做了一个完整的例子,包括为其他用户创建图表。但基本上,您可以将图表图像保存到流而不是文件中
using (MemoryStream stream = new MemoryStream())
{
chart.SaveImage(stream, ChartImageFormat.Png);
}
我创建了一个通用处理程序来在浏览器中显示图像。但是一旦图像进入流,你可以做更多的事情,比如将其放入PDF或电子邮件中
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;
namespace YourNameSpace
{
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//needed to generate random numbers
Random rnd = new Random();
//select 12 random numbers between 1 and 50 for column chart
int[] yRange1 = Enumerable.Range(1, 50).OrderBy(i => rnd.Next()).Take(12).ToArray();
//select 12 random numbers between 1 and 25 for line chart
int[] yRange2 = Enumerable.Range(0, 25).OrderBy(i => rnd.Next()).Take(12).ToArray();
//select all the month names for the labels
string[] xLabels = Enumerable.Range(1, 12).Select(i => DateTimeFormatInfo.CurrentInfo.GetMonthName(i)).ToArray();
//create the chart
Chart chart = new Chart();
//add the bar chart series
Series series = new Series("ChartBar");
series.ChartType = SeriesChartType.Column;
chart.Series.Add(series);
//add the line chart series
Series series2 = new Series("ChartLine");
series2.ChartType = SeriesChartType.Line;
series2.Color = System.Drawing.Color.Purple;
series2.BorderWidth = 2;
chart.Series.Add(series2);
//define the chart area
ChartArea chartArea = new ChartArea();
Axis yAxis = new Axis(chartArea, AxisName.Y);
Axis xAxis = new Axis(chartArea, AxisName.X);
//add the data and define color
chart.Series["ChartBar"].Points.DataBindXY(xLabels, yRange1);
chart.Series["ChartLine"].Points.DataBindXY(xLabels, yRange2);
chart.Series["ChartBar"].Color = System.Drawing.Color.Green;
chart.ChartAreas.Add(chartArea);
//set the dimensions of the chart
chart.Width = new Unit(600, UnitType.Pixel);
chart.Height = new Unit(400, UnitType.Pixel);
//create an empty byte array
byte[] bin = new byte[0];
//save the chart to the stream instead of a file
using (MemoryStream stream = new MemoryStream())
{
chart.SaveImage(stream, ChartImageFormat.Png);
//write the stream to a byte array
bin = stream.ToArray();
}
//send the result to the browser
context.Response.ContentType = "image/png";
context.Response.AddHeader("content-length", bin.Length.ToString());
context.Response.AddHeader("content-disposition", "attachment; filename=\"chart.png\"");
context.Response.OutputStream.Write(bin, 0, bin.Length);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
要在浏览器中显示图像,只需将img元素的src
指向处理程序即可
<img src="Handler1.ashx" width="600" height="400" />
我制作了一个完整的示例,包括为其他用户创建图表。但基本上,您可以将图表图像保存到流而不是文件中
using (MemoryStream stream = new MemoryStream())
{
chart.SaveImage(stream, ChartImageFormat.Png);
}
我创建了一个通用处理程序来在浏览器中显示图像。但是一旦图像进入流,你可以做更多的事情,比如将其放入PDF或电子邮件中
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;
namespace YourNameSpace
{
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//needed to generate random numbers
Random rnd = new Random();
//select 12 random numbers between 1 and 50 for column chart
int[] yRange1 = Enumerable.Range(1, 50).OrderBy(i => rnd.Next()).Take(12).ToArray();
//select 12 random numbers between 1 and 25 for line chart
int[] yRange2 = Enumerable.Range(0, 25).OrderBy(i => rnd.Next()).Take(12).ToArray();
//select all the month names for the labels
string[] xLabels = Enumerable.Range(1, 12).Select(i => DateTimeFormatInfo.CurrentInfo.GetMonthName(i)).ToArray();
//create the chart
Chart chart = new Chart();
//add the bar chart series
Series series = new Series("ChartBar");
series.ChartType = SeriesChartType.Column;
chart.Series.Add(series);
//add the line chart series
Series series2 = new Series("ChartLine");
series2.ChartType = SeriesChartType.Line;
series2.Color = System.Drawing.Color.Purple;
series2.BorderWidth = 2;
chart.Series.Add(series2);
//define the chart area
ChartArea chartArea = new ChartArea();
Axis yAxis = new Axis(chartArea, AxisName.Y);
Axis xAxis = new Axis(chartArea, AxisName.X);
//add the data and define color
chart.Series["ChartBar"].Points.DataBindXY(xLabels, yRange1);
chart.Series["ChartLine"].Points.DataBindXY(xLabels, yRange2);
chart.Series["ChartBar"].Color = System.Drawing.Color.Green;
chart.ChartAreas.Add(chartArea);
//set the dimensions of the chart
chart.Width = new Unit(600, UnitType.Pixel);
chart.Height = new Unit(400, UnitType.Pixel);
//create an empty byte array
byte[] bin = new byte[0];
//save the chart to the stream instead of a file
using (MemoryStream stream = new MemoryStream())
{
chart.SaveImage(stream, ChartImageFormat.Png);
//write the stream to a byte array
bin = stream.ToArray();
}
//send the result to the browser
context.Response.ContentType = "image/png";
context.Response.AddHeader("content-length", bin.Length.ToString());
context.Response.AddHeader("content-disposition", "attachment; filename=\"chart.png\"");
context.Response.OutputStream.Write(bin, 0, bin.Length);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
要在浏览器中显示图像,只需将img元素的src
指向处理程序即可
<img src="Handler1.ashx" width="600" height="400" />
另一种方法是使用图像标记上的base64编码源(via
src=data:image/base64
)将图表直接嵌入html;这还具有不需要任何进一步的http请求就可以从web服务器获取图像的优点
e、 g
这将使用一种方法创建图表,如下所示:
private Chart CreateSomeChart(SomeViewModel vm, int width, int height)
{
int Id = vm.Id;
System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
// usual code to draw a chart here...
return Chart1;
}
在razor视图中编码以获取图表;在我的视图模型中,我有一个图表列表,这些图表只是控制器中要渲染的操作结果方法。使用呈现操作将在html发送到浏览器之前发生,并导致图表以base64编码方式内联
Html.RenderAction方法应该调用的是public ActionResult SomeChart
控制器,对于这个示例Model.ChartList[]={“SomeChart”}
最后一点是getChartImage方法
private string getChartImage(Func<Chart> getChart, object routevals, int width, int height, string chartKey="")
{
string name = "Chart";
if (routevals is SomeViewModel)
{
var cvm = routevals as SomeViewModel;
chartKey = cvm.ChartKey;
name = cvm.ChartKey;
}
using (var stream = new MemoryStream())
{
var Chart1 = getChart();
Chart1.ImageType = ChartImageType.Png;
Chart1.Palette = ChartColorPalette.BrightPastel;
Chart1.SuppressExceptions = true;
// Set chart custom palette
Chart1.Palette = ChartColorPalette.None;
Chart1.PaletteCustomColors = Dashboard.Support.ChartPalettes.ColorsBigList;
Chart1.Width = width;
Chart1.Height = height;
Chart1.RenderType = RenderType.ImageTag;
Chart1.BackColor = Color.White;
Chart1.BackImageAlignment = ChartImageAlignmentStyle.BottomLeft;
Chart1.BorderSkin.SkinStyle = BorderSkinStyle.None;
Chart1.BorderSkin.BorderWidth = 0;
//Chart1.BackImageTransparentColor
Chart1.BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);
Chart1.BorderlineDashStyle = ChartDashStyle.Solid;
Chart1.BorderWidth = 0;
Chart1.SaveImage(stream, ChartImageFormat.Png);
string encoded = Convert.ToBase64String(stream.ToArray());
if (Request != null && Request.Browser != null && Request.Browser.Browser == "IE" && Request.Browser.MajorVersion <= 8)
{
/*
* IE8 can only handle 32k of data inline so do it via the cached getChart
* method - i.e. store the chart in the cache and return a normal image.
*/
if (encoded.Length > 32000)
{
StringBuilder result = new StringBuilder();
if (string.IsNullOrEmpty(chartKey))
chartKey = String.Format("{0}{1}", name, Guid.NewGuid());
System.Web.Helpers.WebCache.Set(chartKey, stream.ToArray());
result.Append(String.Format("<img width='{0}' height='{1}' src='{3}' alt='' usemap='#ImageMap{2}'>", width, height, name,
Url.Action("getChart", new { key = chartKey })));
return result.ToString() + Chart1.GetHtmlImageMap("ImageMap" + name); ;
}
}
/*
* render using data inline for speed
*/
string img = String.Format("<img width='{0}' height='{1}' src='data:image/png;base64,{{0}}' alt='' usemap='#ImageMap{2}'>", Chart1.Width, Chart1.Height, name);
return String.Format(img, encoded) + Chart1.GetHtmlImageMap("ImageMap" + name);
}
}
私有字符串getChartImage(Func-getChart,对象routevals,int-width,int-height,string-chartKey=“”)
{
string name=“Chart”;
if(routevals是SomeViewModel)
{
var cvm=作为SomeViewModel的routevals;
chartKey=cvm.chartKey;
name=cvm.ChartKey;
}
使用(var stream=new MemoryStream())
{
var Chart1=getChart();
Chart1.ImageType=ChartImageType.Png;
Chart1.Palette=ChartColorPalette.BrightPastel;
图表1.1=真;
//设置图表自定义调色板
Chart1.Palette=ChartColorPalette.None;
Chart1.PaletteCustomColors=Dashboard.Support.chartplates.ColorsBigList;
图1.宽度=宽度;
图1.高度=高度;
Chart1.RenderType=RenderType.ImageTag;
图表1.BackColor=颜色。白色;
Chart1.BackImageAlignment=ChartImageAlignmentStyle.BottomLeft;
Chart1.BorderSkin.SkinStyle=BorderSkinStyle.None;
Chart1.BorderSkin.BorderWidth=0;
//图表1.BackImageTransparentColor
Chart1.BorderColor=System.Drawing.Color.FromArgb(26,59,105);
Chart1.BorderlineDashStyle=ChartDashStyle.Solid;
图表1.边界宽度=0;
Chart1.SaveImage(流,ChartImageFormat.Png);
字符串编码=Convert.ToBase64String(stream.ToArray());
if(Request!=null&&Request.Browser!=null&&Request.Browser.Browser==“IE”&&Request.Browser.majorVersion32000)
{
StringBuilder结果=新建StringBuilder();
if(string.IsNullOrEmpty(chartKey))
chartKey=String.Format(“{0}{1}”,名称,Guid.NewGuid());
Set(chartKey,stream.ToArray());
result.Append(String.Format(“),宽度,高度,名称,
Action(“getChart”,new{key=chartKey}));
返回result.ToString()+Chart1.GetHtmlImageMap(“ImageMap”+name);
}
}
/*
*使用数据内联渲染以提高速度
*/
string img=string.Format(“,Chart1.Width,Chart1.Height,name);
返回String.Format(img,encoded)+Chart1.GetHtmlImageMap(“ImageMap”+名称);
}
}
另一种方法是使用图像标记上的base64编码源(viasrc=data:image/base64
)将图表直接嵌入html;这还具有不需要任何进一步的http请求就可以从web服务器获取图像的优点
e、 g
这将使用如下方法创建图表: