C#结合WPF实现审批流程图绘制及后台逻辑的示例详解
作者:code_shenbing
本文将通过完整示例演示如何利用WPF的图形渲染能力与MVVM模式,构建一个可交互的审批流程图系统,并实现审批状态跟踪与业务逻辑处理,需要的朋友可以参考下
一、架构设计:MVVM模式下的审批系统

二、核心实现:流程图绘制引擎
1. 审批节点控件 (XAML)
<!-- ApprovalNodeControl.xaml -->
<ControlTemplate x:Key="NodeTemplate" TargetType="ContentControl">
<Grid>
<!-- 节点基础图形 -->
<Path Data="M 0,0 L 60,0 L 60,40 L 0,40 Z"
Fill="{Binding Status, Converter={StaticResource StatusToColorConverter}}"
Stroke="DarkGray">
<!-- 状态指示灯 -->
<Path.Effect>
<DropShadowEffect Opacity="0.7" BlurRadius="8"
Color="{Binding Status, Converter={StaticResource StatusToShadowColor}}"/>
</Path.Effect>
</Path>
<!-- 节点内容 -->
<StackPanel VerticalAlignment="Center" Margin="10">
<TextBlock Text="{Binding NodeName}" FontWeight="Bold" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Approvers}"
TextTrimming="CharacterEllipsis" MaxWidth="50"/>
</StackPanel>
<!-- 连接锚点 -->
<Ellipse Width="10" Height="10" Fill="Blue"
Canvas.Left="55" Canvas.Top="17"
Visibility="{Binding ShowAnchor, Converter={StaticResource BoolToVisibility}}"/>
</Grid>
</ControlTemplate>2. 动态画布管理器
public class FlowCanvasManager
{
private Canvas _canvas;
private List<ApprovalNodeControl> _nodes = new List<ApprovalNodeControl>();
// 添加新节点
public void AddNode(ApprovalNodeModel nodeModel)
{
var nodeControl = new ApprovalNodeControl(nodeModel);
Canvas.SetLeft(nodeControl, nodeModel.Position.X);
Canvas.SetTop(nodeControl, nodeModel.Position.Y);
// 实现拖拽
nodeControl.MouseMove += (s, e) => {
if (e.LeftButton == MouseButtonState.Pressed)
{
DragDrop.DoDragDrop(nodeControl, nodeModel, DragDropEffects.Move);
}
};
_canvas.Children.Add(nodeControl);
_nodes.Add(nodeControl);
}
// 连接节点
public void ConnectNodes(ApprovalNodeModel from, ApprovalNodeModel to)
{
var connector = new Polyline {
Stroke = Brushes.Gray,
StrokeThickness = 2,
Points = CalculateConnectionPoints(from, to)
};
_canvas.Children.Add(connector);
}
private PointCollection CalculateConnectionPoints(ApprovalNodeModel from, ApprovalNodeModel to)
{
return new PointCollection {
new Point(from.Position.X + 55, from.Position.Y + 20),
new Point(to.Position.X + 5, to.Position.Y + 20)
};
}
}三、审批状态机实现
1. 审批状态与命令管理
public enum ApprovalStatus { Pending, Approved, Rejected, Completed }
public class ApprovalStateMachine
{
private readonly ApprovalFlowModel _flow;
public void ProcessNode(Guid nodeId, bool isApproved)
{
var node = _flow.Nodes.First(n => n.Id == nodeId);
// 状态更新逻辑
node.Status = isApproved ? ApprovalStatus.Approved : ApprovalStatus.Rejected;
// 自动推进逻辑
if (isApproved && node.Type == NodeType.Final)
{
_flow.Status = ApprovalStatus.Completed;
ApprovalCompleted?.Invoke(this, EventArgs.Empty);
}
else if (!isApproved)
{
RollbackToPreviousNode(nodeId);
}
}
private void RollbackToPreviousNode(Guid currentNodeId)
{
// 回溯算法示例
var currentIndex = _flow.Nodes.IndexOf(
_flow.Nodes.First(n => n.Id == currentNodeId));
for (int i = currentIndex - 1; i >= 0; i--)
{
if (_flow.Nodes[i].Status == ApprovalStatus.Approved)
{
_flow.Nodes[i].Status = ApprovalStatus.Pending;
RollbackOccurred?.Invoke(this, i);
break;
}
}
}
// 状态变更事件
public event EventHandler<int> RollbackOccurred;
public event EventHandler ApprovalCompleted;
}2. 基于命令模式的审批操作
public class ProcessApprovalCommand : ICommand
{
private readonly ApprovalStateMachine _stateMachine;
public ProcessApprovalCommand(ApprovalStateMachine stateMachine) =>
_stateMachine = stateMachine;
public bool CanExecute(object parameter) =>
(parameter as ApprovalNodeModel)?.Status == ApprovalStatus.Pending;
public void Execute(object parameter)
{
if (parameter is ApprovalNodeModel node)
{
var dialog = new ApprovalDialog("审批操作");
if (dialog.ShowDialog() == true)
{
_stateMachine.ProcessNode(node.Id, dialog.IsApproved);
}
}
}
public event EventHandler CanExecuteChanged;
}四、UI与后台 完整交互示例
1. 审批流程图定义数据
// 审批流程定义
{
"FlowName": "员工报销流程",
"Nodes": [
{
"Id": "node1",
"NodeName": "提交报销",
"Type": "Start",
"Approvers": ["申请人"],
"Position": { "X": 50, "Y": 100 }
},
{
"Id": "node2",
"NodeName": "部门审批",
"Type": "Approval",
"Approvers": ["部门主管"],
"Position": { "X": 250, "Y": 100 }
}
],
"Connections": [
{"From": "node1", "To": "node2"}
]
}2. 主窗口MVVM绑定
<Window>
<!-- 流程图画布区域 -->
<ScrollViewer>
<Canvas x:Name="MainCanvas" Width="800" Height="600"
Background="#FFF5F5F5">
<!-- 通过ItemsControl动态绑定节点 -->
<ItemsControl ItemsSource="{Binding Flow.Nodes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ApprovalNodeControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</ScrollViewer>
<!-- 审批操作面板 -->
<StackPanel Grid.Column="1">
<Button Content="同意"
Command="{Binding ApproveCommand}"
CommandParameter="{Binding SelectedNode}"/>
<Button Content="驳回"
Command="{Binding RejectCommand}"
CommandParameter="{Binding SelectedNode}"/>
<TextBlock Text="{Binding SelectedNode.Status}" />
</StackPanel>
</Window>五、高级功能实现技巧
1. 可视化状态跟踪
// 状态变更通知
public class ApprovalNodeModel : INotifyPropertyChanged
{
private ApprovalStatus _status;
public ApprovalStatus Status
{
get => _status;
set
{
_status = value;
OnPropertyChanged();
// 状态变更自动记录审计日志
AuditService.Log($"{NodeName}状态变更为{value}");
}
}
}2. 审批规则引擎扩展
// 条件审批示例
public void ApplyApprovalRules()
{
var expenseAmount = GetCurrentExpenseAmount();
if (expenseAmount > 5000)
{
// 自动添加财务总监节点
AddApprovalNode("财务总监审批", NodeType.Approval);
}
else if(expenseAmount > 10000)
{
// 发起加签流程
RequestAdditionalApproval();
}
}3. 流程图序列化保存
public void SaveFlowDiagram()
{
// 生成流程图结构数据
var flowData = new FlowSchema {
Nodes = _nodes.Select(n => n.Model).ToList(),
Connections = FindAllConnections()
};
// 序列化为XML
var serializer = new XmlSerializer(typeof(FlowSchema));
using (var writer = new StreamWriter("flow.xml"))
{
serializer.Serialize(writer, flowData);
}
}六、性能优化建议
图形渲染优化:
// 启用GPU加速 RenderOptions.SetBitmapScalingMode(canvas, BitmapScalingMode.HighQuality); RenderOptions.SetEdgeMode(canvas, EdgeMode.Aliased);
大数据量处理:
// 虚拟化容器
<ItemsControl VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">增量刷新策略:
// 仅刷新变更节点
foreach (var changedNode in _stateMachine.GetChangedNodes())
{
UpdateNodeVisual(changedNode);
}WPF实现审批系统的优势
- 声明式UI开发:XAML数据绑定显著提升UI开发效率
- 强大的图形能力:支持复杂流程图、动画效果、可视化状态反馈
- 完善的MVVM支持:业务逻辑与UI解耦,提升可测试性
- 企业级集成能力:轻松对接WCF/Web API等后端服务
- 桌面端性能优势:相比Web技术有更流畅的用户体验
通过本示例可以看到,结合WPF与C#可构建专业级的审批工作流系统。核心在于灵活运用:
- 自定义控件实现可视化元素
- 状态机管理审批流程
- MVVM模式保持架构清晰
- 命令模式处理用户交互
实际项目中可扩展会签/或签、委托审批、电子签名等企业级功能,打造完整的BPM解决方案。
- 流程设计器(拖拽创建节点)
- 审批规则配置界面
- 流程图导出为PNG/PDF
- 审批历史跟踪时间线
- 多语言本地化支持
以上就是C#结合WPF实现审批流程图绘制及后台逻辑的示例详解的详细内容,更多关于C# WPF审批流程图的资料请关注脚本之家其它相关文章!
