Silverlight WorkFlow画图--主界面处理
画线的流程可以看图(1)
前面几节已经说了ArrowLine、Acivity以及Canvas等控件自己的一些事件处理
这次要说一下就是这几个控件之间怎么关联起来
还是先从图说起吧。
图(1)
图(2)
图(3)
主在界面的运行如上图所示
主界面上用到的变量:
bool isMove; ArrowLine _newLine = null; UIElement _CurrentUIElement; bool _UI_IsMoveing; double _UI_X; double _UI_Y; Color _B_C = Color.FromArgb(0x9B, 0xEF, 0xEE, 0xE5); bool _Is_Activity; private int Index; Dictionary<String, FrameworkElement> DictControls = new Dictionary<string, FrameworkElement>(); private ContextMenu _Cm = new ContextMenu(); private TextBox _txtActivityContent = new TextBox(); public bool Is_Activity { get { return _Is_Activity; } set { _Is_Activity = value; } } List<String> _OperatorHistory = new List<string>();
第一:画线(ArrowLine),流程图图(1)
,首先要判断鼠标点的坐标位置(p = e.GetPosition(canvas))在哪里?在canvas上呢还是在落在canvas画布的其它控件上(Activity),如果不在Activity的话,那好办,鼠标左键按下的时候,_newLine = new ArrowLine(p,p);这样的话线的尾部坐标就出来了;
线的长度:两点连接起来,就是一条线,当鼠标在画布上移动的时候,线的另一点的坐标(线头)也随之发生变化。
线的确定:当鼠标左键弹起来的时候(LeftButtonUp),那么此时一条带箭头线就画完了。
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事件;
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控件里删除掉与当前线的关系。
void _newLine_DeleteLine(object sender, RoutedEventArgs e) { if (sender is ArrowLine) { ArrowLine line = sender as ArrowLine; RemoveArrowLine(line); } } /// <summary> /// 删除线 /// </summary> /// <param name="line"></param> void RemoveArrowLine(IArrowLine line) { if (null == line) { return; } DisposeArrowLine(line); if (line.ArrowCapControl is IActivity) { (line.ArrowCapControl as IActivity).RemoveLine(line); } if (line.ArrowFootControl is IActivity) { (line.ArrowFootControl as IActivity).RemoveLine(line); } var ctl = this.print.FindName(line.CtrName) as UIElement; this.print.Children.Remove(ctl); }
第四:删除Activity控件,流程图图(3)
从Cavnas上面把添加上的Activity控件删除掉,在删除掉Activity的时候,同时也要把与当前相连的ArrowLine线也删除掉,要不能界面上会出在很多无用的线。
void act_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; IActivity iact = sender as IActivity; if (null == iact) { return; } _Cm.Visibility = System.Windows.Visibility.Visible; _Cm.Items.Clear(); var cm = iact.ContextMenu(); foreach (var v in cm) { MenuItem mi = new MenuItem(); mi.Header = v.Header; mi.Tag = v; mi.Click += new RoutedEventHandler(mi_Click); _Cm.Items.Add(mi); } var p = e.GetPosition(print); Canvas.SetLeft(_Cm, p.X); Canvas.SetTop(_Cm, p.Y); Canvas.SetZIndex(_Cm, 1000); } void mi_Click(object sender, RoutedEventArgs e) { _Cm.Visibility = System.Windows.Visibility.Collapsed; MenuItem mi = sender as MenuItem; if (null == mi) { return; } ContextMenuInfo cmi = mi.Tag as ContextMenuInfo; BaseActivity bac = cmi.Source as BaseActivity; switch (cmi.Type) { case ContextMenuType.Delete: RemoveActivity(bac); break; case ContextMenuType.ModifyContent: _ModifyActivityContent(cmi); break; case ContextMenuType.ParameterSettings: _ParameterSettings(cmi, bac); break; } } /// <summary> /// 删除行为控件 /// </summary> /// <param name="bac"></param> void RemoveActivity(BaseActivity bac) { if (null == bac) { return; } List<IArrowLine> items = new List<IArrowLine>(); foreach (var v in bac.DictArrowCapPoint) { items.Add(v.Value); } foreach (var v in bac.DictArrowFootPoint) { items.Add(v.Value); } foreach (var v in items) { RemoveArrowLine(v); } DisposeActivity(bac); DictControls.Remove(bac.Name); this.print.Children.Remove(bac); }
第五:导出Xml
将画完后的流程生成xml,这样可以保存到数据库里或文件里;导出的格式如下情况:
<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>
界面如下图所示:
string GetWorkFlowXml() { List<String> points = new List<string>(); List<String> activitys = new List<string>(); foreach (var v in print.Children) { IImportExport iie = v as IImportExport; if (null == iie) { continue; } points.Add(iie.ExportLocation()); if (v is IActivity) { activitys.Add((v as IActivity).ExportControlRelationship()); } } string _xmlValue = string.Format("<Root>\r\n{0}\r\n{1}\r\n</Root>", string.Format("<Controls Index=\"{0}\">{1}</Controls>", Index, string.Join("\r\n", points)), string.Format("<Relationship>{0}</Relationship>", string.Join("\r\n", activitys))); return XElement.Parse(_xmlValue).ToString(); }
第六:导入XML
将生成好的xml导入进去。
void ImportWorkFlow(XElement root) { if (null == root) { return; } btnClear_Click(null, null); this.print.Children.Add(_Cm); this.print.Children.Add(_txtActivityContent); var controls = root.Element("Controls"); Index = controls.GetAttributeValue("Index").ConvertTo<Int32>(); var activitys = controls.Elements("Activity"); var arrowlines = controls.Elements("ArrowLine"); foreach (var v in arrowlines) { ArrowLineInfo ali = v.ToModel<ArrowLineInfo>(); if (null == ali) { continue; } ArrowLine al = new ArrowLine(ali.StartPoint, ali.EndPoint); al.Name = ali.Name; al.LineGuid = ali.Guid; CreateArrowLine(al); } foreach (var v in activitys) { ActivityInfo ai = v.ToModel<ActivityInfo>(); if (null == ai) { continue; } var config = ParseActivityConfig.GetActivityConfig(ai.Type); if (null == config) { continue; } var ba = Wrapper.CreateControl<BaseActivity>(config.AssemblyQualifiedName); ba.Name = ai.Name; ba.Height = ai.Height; ba.Width = ai.Width; ba.ActivityGUID = ai.Guid; ba.LabelContent = ai.Content.IsNullOrEmpty() ? config.Description : ai.Content; ba.CurrentLeftButtonDownPoint = ai.CurrentLeftButtonDownPoint; ba.CurrentEnterPoint = ai.CurrentEnterPoint; CreateActivity(ba); Canvas.SetTop(ba, ai.Top); Canvas.SetLeft(ba, ai.Left); } //-->规则 var rules = root.Element("Relationship"); var rulesControl = rules.Elements("Control"); foreach (var rule in rulesControl) { string _r_name = rule.GetAttributeValue("Name"); BaseActivity iact = GetControlByName<BaseActivity>(_r_name); if (null == iact) { continue; } var caps = rule.GetAttributeValue("Cap"); if (!caps.IsNullOrEmpty()) { var capArray = caps.Split('|'); foreach (var cap in capArray) { ArrowLine _al = GetControlByName<ArrowLine>(cap); if (null == _al) { continue; } _al.ArrowFootControl = iact; iact.DictArrowCapPoint.Add(_al.Name, _al); } } var foots = rule.GetAttributeValue("Foot"); if (!foots.IsNullOrEmpty()) { var footArray = foots.Split('|'); foreach (var foot in footArray) { ArrowLine _al = GetControlByName<ArrowLine>(foot); if (null == _al) { continue; } _al.ArrowCapControl = iact; iact.DictArrowFootPoint.Add(_al.CtrName, _al); } } } }
到这里主界面的处理基本上说完了
Silverlight WorkFlow画图源代码