首先慶祝一下源代碼在codeplex上下載量超過1000。另外本演示程序放在微軟免費的silverlight host上面,您也可以申請免費的空間。地址在http://silverlight.live.com/。
在silverlight中并沒有提供生成圖片的相關(guān)類,網(wǎng)上搜索了一下,得到的結(jié)果是微軟并沒有打算在silverlight中提供對System.Drawring及其相關(guān)類的支持。正路走不通,只能繞路走了。
首先慶祝一下源代碼在codeplex上下載量超過1000
另外本演示程序放在微軟免費的silverlight host上面,您也可以申請免費的空間。
地址在http://silverlight.live.com/
技術(shù)支持QQ群:85444465
源代碼下載:http://www.shareidea.net/opensource.htm
在線演示:http://www.shareidea.net/workflow.htm
視頻教程: http://www.shareidea.net/video/sharedesigner/sharedesigner.html
本文系列索引:
使用silverlight構(gòu)建一個工作流設(shè)計器(一)
使用silverlight構(gòu)建一個工作流設(shè)計器(二)
使用silverlight構(gòu)建一個工作流設(shè)計器(三)
使用silverlight構(gòu)建一個工作流設(shè)計器(四)
使用silverlight構(gòu)建一個工作流設(shè)計器(五)
使用silverlight構(gòu)建一個工作流設(shè)計器(六)
使用silverlight構(gòu)建一個工作流設(shè)計器(七)
使用silverlight構(gòu)建一個工作流設(shè)計器(八)
使用silverlight構(gòu)建一個工作流設(shè)計器(九)
使用silverlight構(gòu)建一個工作流設(shè)計器(十)
使用silverlight構(gòu)建一個工作流設(shè)計器(十一)
使用silverlight構(gòu)建一個工作流設(shè)計器(十二)
使用silverlight構(gòu)建一個工作流設(shè)計器(十三)
9.1問題描述
今天有網(wǎng)友問,這個工作流設(shè)計器能不能生成對應的圖片呢?我想不出生成圖片能有什么作用,如果想用圖片,我們大可以使用拷屏的方法保存到畫圖中,然后再保存在系統(tǒng)文件夾。不過作為一種嘗試,不妨去試著去實現(xiàn)這個功能。
9.2遇到的困難
動態(tài)生成圖片,首先想到的就是使用System.Drawring相關(guān)的類,但在silverlight中并沒有提供對System.Drawring的支持,網(wǎng)上查了一下,得到的答案是微軟并沒有打算在silverlight中提供對System.Drawring的支持。
另外,在silverlight中無法直接進行文件的保存操作。
這些困難都說明,要想在silverlight中直接生成圖片并保存,目前是不可行的。
9.3解決方法
雖然我們不能直接在silverlight中生成圖片保存,但我們的目的的生成圖片,至于在什么地方生成圖片,并沒有固定的要求。我們知道,在asp.net中,我們經(jīng)常使用System.Drawring相關(guān)類在動態(tài)生成圖片,這個方法提醒我們,可以將生成圖片的方法延遲到后臺的服務中,然后訪問后臺生成的圖片即可。用下面的圖片來表示整個流程。

上面是一個理想的執(zhí)行過程,但是在實際應用中發(fā)現(xiàn)有疑點問題,就是在生成圖片后回調(diào)silverlight的函數(shù)中無法打開一個新的網(wǎng)頁。只能把打開網(wǎng)頁的代碼放在按鈕點擊事件中,不過這對用戶來說沒有任何影響,只不過我們需要多做一點工作而已。在下面的代碼中體現(xiàn)了這一點不同。
9.3.1 建立webservices文件
建立一個webservice文件,命名為createPic.asmx,在后臺代碼中根據(jù)傳入的流程圖xml描述文件動態(tài)生成圖片。對應的框架代碼如下:

Code
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
namespace ShareDesigner.Web
{
/// <summary>
/// Summary description for CreatePic
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class CreatePic : System.Web.Services.WebService
{
public class RulePicture
{
public void DrawingPic(Graphics gr) { }
}
public class ActivityPicture
{
public void DrawingPic(Graphics gr) { }
}
public class ContainerPicture
{
public void ParseWorkFlowXML(string xmlString)
{
}
int _width = 400;
public int Width { get { return _width; } }
int _height = 200;
public int Height { get { return _height; } }
List<RulePicture> _rulePictureCollection;
public List<RulePicture> RulePictureCollection
{
get
{
if (_rulePictureCollection == null)
_rulePictureCollection = new List<RulePicture>();
return _rulePictureCollection;
}
}
List<ActivityPicture> _activityPictureCollection;
public List<ActivityPicture> ActivityPictureCollection
{
get
{
if (_activityPictureCollection == null)
_activityPictureCollection = new List<ActivityPicture>();
return _activityPictureCollection;
}
}
}
[WebMethod]
public void CreatePicture(string pictureName,string xml)
{
ContainerPicture con = new ContainerPicture();
con.ParseWorkFlowXML(xml);
Bitmap pg = new Bitmap(con.Width, con.Height);
Graphics gr = Graphics.FromImage(pg);
for (int i = 0; i < con.RulePictureCollection.Count; i++)
{
con.RulePictureCollection[i].DrawingPic(gr);
}
for (int i = 0; i < con.ActivityPictureCollection.Count; i++)
{
con.ActivityPictureCollection[i].DrawingPic(gr);
}
Font fn = new Font("@宋體", 12);
SolidBrush solidBlack = new SolidBrush(Color.Red);
gr.DrawString(pictureName, fn, solidBlack, (int)(pg.Width * 0.1), (int)(pg.Height * 0.1));
MemoryStream stream = new MemoryStream();
pg.Save(Server.MapPath("~/picture/" + pictureName+".png"), System.Drawing.Imaging.ImageFormat.Png);
}
}
}
9.3.2 添加webservice引用
具體方法請參考http://kb.cnblogs.com/page/42888/?page=1
在流程容器頁面Container.xaml添加一個按鈕,在按鈕事件中編寫訪問生成圖片的代碼,同時開發(fā)一個頁面瀏覽生成的圖片,代碼如下所示,請注意其中的注釋內(nèi)容,另外,如果我們將項目部署到服務器上給客戶用,那么需要修改動態(tài)設(shè)定服務路徑,在下面的代碼中有所體現(xiàn)。

Code
string picName = "";
//連接創(chuàng)建圖片服務,打開新的窗口訪問圖片
private void btnCreatePicture_Click(object sender, RoutedEventArgs e)
{
picName = Guid.NewGuid().ToString();
System.ServiceModel.BasicHttpBinding bind = new System.ServiceModel.BasicHttpBinding();
System.ServiceModel.EndpointAddress endpoint = new System.ServiceModel.EndpointAddress(
new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, "createpic.asmx"), null);
CreatePicture.CreatePicSoapClient client = new Shareidea.Web.UI.Control.Workflow.Designer.CreatePicture.CreatePicSoapClient(bind, endpoint);
client.CreatePictureCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_CreatePictureCompleted);
client.CreatePictureAsync(picName, ToXmlString());
Uri url = new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, "picture.aspx?name=" + picName);
System.Windows.Browser.HtmlPage.PopupWindow(url, "_blank", null);
}
void client_CreatePictureCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
//下面這段代碼無法彈出新的窗口,只能上面的方法中才能執(zhí)行
// Uri url = new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, "picture.aspx?name=" + picName);
// System.Windows.Browser.HtmlPage.PopupWindow(url, "_blank", null);
}
9.3.3 建立圖片顯示頁面
建立一個picture.aspx。這個文件接受一個參數(shù)pictureName,接受上一部的文件名稱。根據(jù)參數(shù)檢查是否存在這樣的文件,如果存在,則將內(nèi)容發(fā)送到客戶端,如果不存在,那么顯示一個錯誤消息,代入如下所示:

Code
protected void Page_Load(object sender, EventArgs e)
{
string fileName = "";
if (Page.Request.QueryString["name"] != null)
fileName = Page.Request.QueryString["name"].ToString();
string filePath=Server.MapPath("~/picture/"+fileName+".png");
FileInfo info = null;
long size = 0;
info = new FileInfo(filePath);
int seconds = 0;
while (!info.Exists && seconds <5)
{
info = new FileInfo(filePath);
System.Threading.Thread.Sleep(1000);
seconds++;
}
if (info.Exists)
{
size = info.Length;
Response.ClearContent();
Response.ContentType = "image/png";
Response.WriteFile(filePath, 0, size);
Response.End();
}
Response.Write("您請求的圖片不存在!");
}
到現(xiàn)在為止,一個動態(tài)生成流程圖圖片的框架就完成了,因為還沒有編寫具體的活動和規(guī)則的圖片生成方法,所以只是生成一個顯示文件名稱的圖片。下一章將具體完成生成圖片的代碼。