为何需要流程图?
用户可以清晰的看到流程参与对象、流程节点状态及其整个流程结构;
因为WF4设计器本身没有天然提供这一功能,所以还需自己动手DIY;生成窗体图片因为需要用到底层GUI功能,所以是单独建立一个WPF工程,然后通过暴露服务的方式,实现同步调用,并返回数据;
功能实现及其步骤:
1.加载流程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary>
/// 加载流程设计器
/// </summary>
/// <param name="instance"></param>
private void LoadWorkflowDesigner(System.Activities.Activity instance)
{
(new DesignerMetadata()).Register();
_workflowDesigner = new WorkflowDesigner();
if (instance is System.Activities.DynamicActivity)
{
instance = System.Activities.WorkflowInspectionServices.GetActivities(instance).First();
}
_workflowDesigner.Load(instance);
this.rehostGrid.Children.Clear();
this.rehostGrid.Children.Add(_workflowDesigner.View);
_workflowDesigner.View.LayoutUpdated += new EventHandler(View_LayoutUpdated);
}
2.利用控件截图功能,实现对设计器控件截图;
/// <summary>
/// 创建屏幕截图
/// </summary>
/// <returns></returns>
BitmapFrame CreateScreenShot()
{
const double DPI = 96.0;
// 获取设计器下的主窗体设计器,this._workflowDesigner.View是指整个容器,容器包含的第一个子窗体才是主窗体设计器
DesignerView designerView = (DesignerView)VisualTreeHelper.GetChild(this._workflowDesigner.View, 0);
Visual visual = designerView.RootDesigner;
Rect size = VisualTreeHelper.GetDescendantBounds(visual);
int imageWidth = (int)size.Width;
int imageHeight = (int)size.Height;
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(imageWidth, imageHeight, DPI, DPI, PixelFormats.Pbgra32);
renderBitmap.Render(visual);
return BitmapFrame.Create(renderBitmap);
}
/// <summary>
3.两种生成图的方式;a.生成图然后返回图片路径 b.直接返回生成后的二进制数据
/// <summary>
/// 获取二进制图片数据
/// </summary>
/// <returns></returns>
public byte[] GetPictureBytes()
{
Dispatcher.Invoke((Action)(() =>
{
try
{
MemoryStream ms = new MemoryStream();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(this.CreateScreenShot()));
encoder.Save(ms);
ms.Close();
ImageBytes = ms.ToArray();
}catch(Exception ex)
{ MessageBox.Show(ex.Message); }
// 关闭窗口
this.Close();
// 优先级必须为System.Windows.Threading.DispatcherPriority.Background,否则流程图会生成不全;
}), System.Windows.Threading.DispatcherPriority.Background);
return ImageBytes;
}
/// <summary>
/// 创建本地图片
/// </summary>
/// <param name="fileName">生成图片文件名称</param>
/// <returns>是否生成成功</returns>
public bool CreateLocalPircture(string fileName)
{
bool b = false;
Dispatcher.Invoke((Action)(() =>
{
try
{
string fileDirectory = fileName.Substring(0, (fileName.LastIndexOf('\\') + 1));
// 如果目录不存在,则创建
if (!Directory.Exists(fileDirectory))
{
Directory.CreateDirectory(fileDirectory);
}
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
BitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(this.CreateScreenShot()));
encoder.Save(fs);
fs.Close();
}
b = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
// 关闭窗口
this.Close();
// 优先级必须为System.Windows.Threading.DispatcherPriority.Background,否则流程图会生成不全;
}), System.Windows.Threading.DispatcherPriority.Background);
return b;
}
3.WCF调用生成流程窗体
[ServiceContract]
public interface IWFPictureFactory
{
/// <summary>
/// 根据申请ID获取二进制图片数据
/// </summary>
/// <param name="aiid">申请ID</param>
/// <returns></returns>
[OperationContract]
byte[] GetPictureBytes(int aiid);
/// <summary>
/// 根据申请ID和图片文件名称生成本地图片
/// </summary>
/// <param name="aiid">申请ID</param>
/// <param name="filename">文件名称</param>
/// <returns></returns>
[OperationContract]
bool CreateLocalPircture(int aiid, string filename);
}
public class WFPictureFactory : IWFPictureFactory
{
/// <summary>
/// 根据申请ID获取二进制图片数据
/// </summary>
/// <param name="aiid">申请ID</param>
/// <returns></returns>
public byte[] GetPictureBytes(int aiid)
{
MainWindow window = new MainWindow();
window.AIID = aiid;
window.Show();
var bytes= window.GetPictureBytes();
return bytes;
}
/// <summary>
/// 根据申请ID和图片文件名称生成本地图片
/// </summary>
/// <param name="aiid">申请ID</param>
/// <param name="filename">文件名称</param>
/// <returns></returns>
public bool CreateLocalPircture(int aiid,string filename)
{
MainWindow window = new MainWindow();
window.AIID = aiid;
window.Show();
var b = window.CreateLocalPircture(filename);
return b;
}
4.启动/关闭服务
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ServiceHost myServiceHost = null;
void StartService(Type type)
{
try
{
//Instantiate new ServiceHost with the singleton instance being passed in
myServiceHost = new ServiceHost(type);
myServiceHost.Open();
lblMsg.Content = "服务已启动!";
}
catch(Exception ex) {
lblMsg.Content = "启动失败!";
System.Windows.MessageBox.Show(ex.Message);
}
}
void StopService()
{
if(myServiceHost!=null){
try
{
myServiceHost.Close();
lblMsg.Content = "服务已关闭!";
}
catch (Exception ex)
{
lblMsg.Content = "关闭服务失败!";
System.Windows.MessageBox.Show(ex.Message);
}
}
}
未完待续ing!下一步攻克流程节点状态显示的问题!
Demo下载:https://files.cnblogs.com/yizhuqing/AWFP.WFPictureBuilder.zip