Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何纯粹从codebehind创建动态内存ASP.NET图表?_C#_Asp.net_Charts - Fatal编程技术网

C# 如何纯粹从codebehind创建动态内存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

我正在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...]

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编码源(via
src=data:image/base64
)将图表直接嵌入html;这还具有不需要任何进一步的http请求就可以从web服务器获取图像的优点

e、 g

这将使用如下方法创建图表: