畫線的流程可以看圖(1)前面幾節已經說了ArrowLine、Acivity以及Canvas等控件自己的一些事件處理
這次要說一下就是這幾個控件之間怎么關聯起來
還是先從圖說起吧。

圖(1)

圖(2)

圖(3)
主在界面的運行如上圖所示
主界面上用到的變量:
View Code
1 bool isMove;
2 ArrowLine _newLine = null;
3 UIElement _CurrentUIElement;
4 bool _UI_IsMoveing;
5 double _UI_X;
6 double _UI_Y;
7 bool _Is_Activity;
8 private int Index;
9 Dictionary<String, FrameworkElement> DictControls = new Dictionary<string, FrameworkElement>();
10 private ContextMenu _Cm = new ContextMenu();
11 private TextBox _txtActivityContent = new TextBox();
12 public bool Is_Activity { get { return _Is_Activity; } set { _Is_Activity = value; } }
13 List<String> _OperatorHistory = new List<string>();
第一:畫線(ArrowLine),流程圖圖(1)
,首先要判斷鼠標點的坐標位置(p = e.GetPosition(canvas))在哪里?在canvas上呢還是在落在canvas畫布的其它控件上(Activity),如果不在Activity的話,那好辦,鼠標左鍵按下的時候,_newLine = new ArrowLine(p,p);這樣的話線的尾部坐標就出來了;
線的長度:兩點連接起來,就是一條線,當鼠標在畫布上移動的時候,線的另一點的坐標(線頭)也隨之發生變化。
線的確定:當鼠標左鍵彈起來的時候(LeftButtonUp),那么此時一條帶箭頭線就畫完了。
View Code
void act_DotMouseLeave(object sender, MouseEventArgs e)
{
Is_Activity = false;
}
void act_DotMouseEnter(object sender, MouseEventArgs e)
{
_Is_Activity = true;
}
void act_DotMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(print);
if (_newLine != null && p == _newLine.StartPoint)
{
return;
}
print_MouseLeftButtonDown(print, e);
IActivity lb = sender as IActivity;
if (!lb.IsStart())
{
MessageBox.Show("不能開始");
if (null != _newLine)
{
RemoveArrowLine(_newLine);
}
return;
}
//-->記住當前的節點開始坐標
lb.DictArrowFootPoint.Add(_newLine.Name, _newLine);
_newLine.ArrowFootControl = sender as UIElement;
}
void act_DotMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (Is_Activity && null != _newLine)
{
//-->又到里面去了,不用創建此箭頭
RemoveArrowLine(_newLine);
}
print_MouseLeftButtonUp(print, e);
var p = e.GetPosition(print);
//-->更新所有箭頭坐標。
IActivity lb = sender as IActivity;
lb.UpdateArrowCapPoint(p);
lb.UpdateArrowFootPoint(p);
_newLine = null;
}
void act_DotMouseMove(object sender, MouseEventArgs e)
{
print_MouseMove(print, e);
}
第二:Activity的移動,流程圖圖(1)
當鼠標左鍵按下首先是觸發控件本身的LeftButtonDown事件,去調用Canvas的LeftButtonDown;
鼠標移動的時候,同理,去調用Canvas的Move事件;時時的更新新的坐標位置,以及Activity里面的線的坐標(如果線是連進來的話,修改線的箭頭坐標;如果是線從這里出發的,修改線箭尾坐標);
彈起來的同理也是調用Canvas的LeftButtonUp事件;
View Code
void act_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UIElement uie = sender as UIElement;
if (null == uie)
{
return;
}
uie.CaptureMouse();
var p = e.GetPosition(print);
double _UI_Left = Canvas.GetLeft(uie);
double _UI_Top = Canvas.GetTop(uie);
IActivity act = sender as IActivity;
if (Is_Activity && null != act && act.IsStart())
{
print_MouseLeftButtonDown(print, e);
}
else
{
_UI_X = p.X - _UI_Left;
_UI_Y = p.Y - _UI_Top;
_UI_IsMoveing = true;
e.Handled = true;
}
if (null != act && act.IsStart())
{
p = new Point(_UI_Left, _UI_Top);
(sender as IActivity).CurrentLeftButtonDownPoint = p;
}
}
void act_MouseMove(object sender, MouseEventArgs e)
{
if (!_UI_IsMoveing)
{
return;
}
var p = e.GetPosition(print);
var p1 = new Point();
if (Is_Activity)
{
print_MouseMove(print, e);
}
else
{
UIElement uie = sender as UIElement;
if (null == uie || _UI_IsMoveing == false)
{
return;
}
double newLeft = p.X;
double newTop = p.Y;
p1.X = newLeft - _UI_X;
p1.Y = newTop - _UI_Y;
Canvas.SetLeft(uie, newLeft - _UI_X);
Canvas.SetTop(uie, newTop - _UI_Y);
}
//-->當箭頭移動到控件上時
if (sender is IActivity)
{
(sender as IActivity).UpdateArrowCapPoint(p1);
(sender as IActivity).UpdateArrowFootPoint(p1);
}
}
void act_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = false;
_UI_IsMoveing = false;
Is_Activity = false;
var p = e.GetPosition(print);
if (Is_Activity)
{
print_MouseLeftButtonUp(print, e);
}
else
{
UIElement uie = sender as UIElement;
if (null == uie)
{
return;
}
double newLeft = p.X;
double newTop = p.Y;
Canvas.SetLeft(uie, newLeft - _UI_X);
Canvas.SetTop(uie, newTop - _UI_Y);
uie.ReleaseMouseCapture();
}
if (sender is IActivity)
{
p = new Point(p.X - _UI_X, p.Y - _UI_Y);
(sender as IActivity).UpdateArrowCapPoint(p);
(sender as IActivity).UpdateArrowFootPoint(p);
}
_newLine = null;
string a = GetWorkFlowXml();
if (_OperatorHistory.Count > 50)
{
_OperatorHistory.RemoveAt(_OperatorHistory.Count - 1);
}
_OperatorHistory.Insert(0, a);
}
第三:刪除線(ArrowLine),流程圖圖(2)
如圖畫錯了,或不用了,刪除Canvas上的線的時候,在刪除線的時候,找出兩頭(箭頭、箭尾的兩Activity控件),找出來后,從Activity控件里刪除掉與當前線的關系。
View Code
1 void _newLine_DeleteLine(object sender, RoutedEventArgs e)
2 {
3 if (sender is ArrowLine)
4 {
5 ArrowLine line = sender as ArrowLine;
6 RemoveArrowLine(line);
7 }
8 }
9 /// <summary>
10 /// 刪除線
11 /// </summary>
12 /// <param name="line"></param>
13 void RemoveArrowLine(IArrowLine line)
14 {
15 if (null == line)
16 {
17 return;
18 }
19 DisposeArrowLine(line);
20 if (line.ArrowCapControl is IActivity)
21 {
22 (line.ArrowCapControl as IActivity).RemoveLine(line);
23 }
24 if (line.ArrowFootControl is IActivity)
25 {
26 (line.ArrowFootControl as IActivity).RemoveLine(line);
27 }
28 var ctl = this.print.FindName(line.CtrName) as UIElement;
29 this.print.Children.Remove(ctl);
30 }
第四:刪除Activity控件,流程圖圖(3)
從Cavnas上面把添加上的Activity控件刪除掉,在刪除掉Activity的時候,同時也要把與當前相連的ArrowLine線也刪除掉,要不能界面上會出在很多無用的線。
View Code
1 void act_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
2 {
3 e.Handled = true;
4 IActivity iact = sender as IActivity;
5 if (null == iact)
6 {
7 return;
8 }
9 _Cm.Visibility = System.Windows.Visibility.Visible;
10 _Cm.Items.Clear();
11 var cm = iact.ContextMenu();
12 foreach (var v in cm)
13 {
14 MenuItem mi = new MenuItem();
15 mi.Header = v.Header;
16 mi.Tag = v;
17 mi.Click += new RoutedEventHandler(mi_Click);
18 _Cm.Items.Add(mi);
19 }
20 var p = e.GetPosition(print);
21 Canvas.SetLeft(_Cm, p.X);
22 Canvas.SetTop(_Cm, p.Y);
23 Canvas.SetZIndex(_Cm, 1000);
24 }
25
26 void mi_Click(object sender, RoutedEventArgs e)
27 {
28 _Cm.Visibility = System.Windows.Visibility.Collapsed;
29 MenuItem mi = sender as MenuItem;
30 if (null == mi)
31 {
32 return;
33 }
34 ContextMenuInfo cmi = mi.Tag as ContextMenuInfo;
35 BaseActivity bac = cmi.Source as BaseActivity;
36 switch (cmi.Type)
37 {
38 case ContextMenuType.Delete:
39 RemoveActivity(bac);
40 break;
41 case ContextMenuType.ModifyContent:
42 _ModifyActivityContent(cmi);
43 break;
44 case ContextMenuType.ParameterSettings:
45 _ParameterSettings(cmi, bac);
46 break;
47 }
48 }
49 /// <summary>
50 /// 刪除行為控件
51 /// </summary>
52 /// <param name="bac"></param>
53 void RemoveActivity(BaseActivity bac)
54 {
55 if (null == bac)
56 {
57 return;
58 }
59 List<IArrowLine> items = new List<IArrowLine>();
60 foreach (var v in bac.DictArrowCapPoint)
61 {
62 items.Add(v.Value);
63 }
64 foreach (var v in bac.DictArrowFootPoint)
65 {
66 items.Add(v.Value);
67 }
68 foreach (var v in items)
69 {
70 RemoveArrowLine(v);
71 }
72 DisposeActivity(bac);
73 DictControls.Remove(bac.Name);
74 this.print.Children.Remove(bac);
75 }
第五:導出Xml
將畫完后的流程生成xml,這樣可以保存到數據庫里或文件里;導出的格式如下情況:
View Code
<Root>
<Controls Index="12">
<ArrowLine Type="ArrowLine" Name="ArrowLine_7" Guid="5F369FE59F14436C80F8CDBBA6853569" StartX="316" StartY="44" EndX="319" EndY="197" />
<ArrowLine Type="ArrowLine" Name="ArrowLine_8" Guid="F40D6856081541DA8E538A4DF827BEB8" StartX="317" StartY="208" EndX="235" EndY="299" />
<ArrowLine Type="ArrowLine" Name="ArrowLine_9" Guid="E20DC22E807D46ED8A0144361AD75E28" StartX="335" StartY="194" EndX="426" EndY="293" />
<ArrowLine Type="ArrowLine" Name="ArrowLine_10" Guid="F0C2F179254B434C9BBBD4FBFBEBC6DC" StartX="237" StartY="314" EndX="324" EndY="438" />
<ArrowLine Type="ArrowLine" Name="ArrowLine_11" Guid="6743E207BE584FD3BD4B6E47740FB9C5" StartX="434" StartY="301" EndX="325" EndY="440" />
<ArrowLine Type="ArrowLine" Name="ArrowLine_12" Guid="273360D936A443029FC6382859C3E0BD" StartX="583" StartY="200" EndX="320" EndY="197" />
<Activity Type="BeginActivity" Name="Activity_BeginActivity_1" Guid="E760B54B3C844CDE85D1F3FE7F4447E7" Width="100" Height="40" Left="282" Top="18" Content="開始節點" EnterX="282" EnterY="18" />
<Activity Type="EndActivity" Name="Activity_EndActivity_2" Guid="C4C25E447FA342608D1B449D2E027352" Width="100" Height="40" Left="277" Top="422" Content="結束節點" EnterX="277" EnterY="422" />
<Activity Type="JudgeActivity" Name="Activity_JudgeActivity_3" Guid="0B483330600549DB9EEBD9D7488D40F1" Width="100" Height="40" Left="270" Top="177" Content="判斷節點" EnterX="270" EnterY="177" />
<Activity Type="LabelActivity" Name="Activity_LabelActivity_4" Guid="95F9AC3DDBCA4CC78FC4022E5247829D" Width="100" Height="40" Left="547" Top="177" Content="標簽節點" EnterX="547" EnterY="177" />
<Activity Type="HandlingProcessActivity" Name="Activity_HandlingProcessActivity_5" Guid="EA15001637A84B2099B9860796C2B7E2" Width="100" Height="40" Left="383" Top="271" Content="處理進程" EnterX="383" EnterY="271" />
<Activity Type="DatabaseActivity" Name="Activity_DatabaseActivity_6" Guid="98E67A2182E14FF4B7B4BB4C334E1CD6" Width="100" Height="40" Left="186" Top="282" Content="調用數據庫" EnterX="186" EnterY="282" />
<Activity Type="CallCtrlFunctionActivity" Name="Activity_CallCtrlFunctionActivity_1" Guid="D167DAE5D0564E8EB9E9D50A57C426FA" Width="100" Height="40" Left="564" Top="275" Content="Call Function" EnterX="564" EnterY="275" />
</Controls>
<Relationship>
<Control Name="Activity_BeginActivity_1" Cap="" Foot="ArrowLine_7" />
<Control Name="Activity_EndActivity_2" Cap="ArrowLine_10|ArrowLine_11" Foot="" />
<Control Name="Activity_JudgeActivity_3" Cap="ArrowLine_7|ArrowLine_12" Foot="ArrowLine_8|ArrowLine_9" />
<Control Name="Activity_LabelActivity_4" Cap="" Foot="ArrowLine_12" />
<Control Name="Activity_HandlingProcessActivity_5" Cap="ArrowLine_9" Foot="ArrowLine_11" />
<Control Name="Activity_DatabaseActivity_6" Cap="ArrowLine_8" Foot="ArrowLine_10" />
<Control Name="Activity_CallCtrlFunctionActivity_1" Cap="" Foot="" />
</Relationship>
</Root>
界面如下圖所示:

View Code
1 string GetWorkFlowXml()
2 {
3 List<String> points = new List<string>();
4 List<String> activitys = new List<string>();
5 foreach (var v in print.Children)
6 {
7 IImportExport iie = v as IImportExport;
8 if (null == iie)
9 {
10 continue;
11 }
12 points.Add(iie.ExportLocation());
13 if (v is IActivity)
14 {
15 activitys.Add((v as IActivity).ExportControlRelationship());
16 }
17 }
18 string _xmlValue = string.Format("<Root>\r\n{0}\r\n{1}\r\n</Root>",
19 string.Format("<Controls Index=\"{0}\">{1}</Controls>", Index, string.Join("\r\n", points)),
20 string.Format("<Relationship>{0}</Relationship>", string.Join("\r\n", activitys)));
21 return XElement.Parse(_xmlValue).ToString();
22 }
第六:導入XML
將生成好的xml導入進去。
View Code
1 void ImportWorkFlow(XElement root)
2 {
3 if (null == root)
4 {
5 return;
6 }
7 btnClear_Click(null, null);
8 this.print.Children.Add(_Cm);
9 this.print.Children.Add(_txtActivityContent);
10 var controls = root.Element("Controls");
11 Index = controls.GetAttributeValue("Index").ConvertTo<Int32>();
12 var activitys = controls.Elements("Activity");
13 var arrowlines = controls.Elements("ArrowLine");
14 foreach (var v in arrowlines)
15 {
16 ArrowLineInfo ali = v.ToModel<ArrowLineInfo>();
17 if (null == ali)
18 {
19 continue;
20 }
21 ArrowLine al = new ArrowLine(ali.StartPoint, ali.EndPoint);
22 al.Name = ali.Name;
23 al.LineGuid = ali.Guid;
24 CreateArrowLine(al);
25 }
26 foreach (var v in activitys)
27 {
28 ActivityInfo ai = v.ToModel<ActivityInfo>();
29 if (null == ai)
30 {
31 continue;
32 }
33
34 var config = ParseActivityConfig.GetActivityConfig(ai.Type);
35 if (null == config)
36 {
37 continue;
38 }
39 var ba = Wrapper.CreateControl<BaseActivity>(config.AssemblyQualifiedName);
40 ba.Name = ai.Name;
41 ba.Height = ai.Height;
42 ba.Width = ai.Width;
43 ba.ActivityGUID = ai.Guid;
44 ba.LabelContent = ai.Content.IsNullOrEmpty() ? config.Description : ai.Content;
45 ba.CurrentLeftButtonDownPoint = ai.CurrentLeftButtonDownPoint;
46 ba.CurrentEnterPoint = ai.CurrentEnterPoint;
47 CreateActivity(ba);
48 Canvas.SetTop(ba, ai.Top);
49 Canvas.SetLeft(ba, ai.Left);
50 }
51
52 //-->規則
53 var rules = root.Element("Relationship");
54 var rulesControl = rules.Elements("Control");
55 foreach (var rule in rulesControl)
56 {
57 string _r_name = rule.GetAttributeValue("Name");
58 BaseActivity iact = GetControlByName<BaseActivity>(_r_name);
59 if (null == iact)
60 {
61 continue;
62 }
63 var caps = rule.GetAttributeValue("Cap");
64 if (!caps.IsNullOrEmpty())
65 {
66 var capArray = caps.Split('|');
67 foreach (var cap in capArray)
68 {
69 ArrowLine _al = GetControlByName<ArrowLine>(cap);
70 if (null == _al)
71 {
72 continue;
73 }
74 _al.ArrowFootControl = iact;
75 iact.DictArrowCapPoint.Add(_al.Name, _al);
76 }
77 }
78 var foots = rule.GetAttributeValue("Foot");
79 if (!foots.IsNullOrEmpty())
80 {
81 var footArray = foots.Split('|');
82 foreach (var foot in footArray)
83 {
84 ArrowLine _al = GetControlByName<ArrowLine>(foot);
85 if (null == _al)
86 {
87 continue;
88 }
89 _al.ArrowCapControl = iact;
90 iact.DictArrowFootPoint.Add(_al.CtrName, _al);
91 }
92 }
93 }
94 }
到這里主界面的處理基本上說完了
