本章包含以下內(nèi)容:1、規(guī)則曲線支持兩個中間點的移動。2、雙擊規(guī)則中間點,自定對齊曲線。3、增加選定活動的左右、上下對齊功能。
源代碼下載:http://www.shareidea.net/opensource.htm
在線演示:http://www.shareidea.net/workflow.htm
視頻教程: http://www.shareidea.net/video/sharedesigner/sharedesigner.html
技術(shù)支持QQ群:85444465
本文系列索引:
使用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è)計器(十一)
本章包含以下內(nèi)容:
l 規(guī)則曲線支持兩個中間點的移動
l 雙擊規(guī)則中間點,自定對齊曲線
l 增加選定活動的左右、上下對齊功能
6.8規(guī)則曲線支持兩個中間點的移動
在前面的規(guī)則圖形中,也支持曲線類型的線條,但是線條的轉(zhuǎn)折點是自動生成的,根據(jù)網(wǎng)友的反饋,希望增加可以用戶自己移動的轉(zhuǎn)折點,效果圖如下:

為了使得程序清晰,更加面向?qū)ο螅瑢τ谵D(zhuǎn)折點我們使用一個單獨的類(用戶控件)來表示,這個轉(zhuǎn)折點類只包含一個圓(Ellipse)。Xmal代碼如下:

Code
<UserControl x:Class="Shareidea.Web.UI.Control.Workflow.Designer.RuleTurnPoint"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Canvas>
<Canvas.Resources>
<Storyboard x:Name="sbDisplay">
<DoubleAnimation From="0" To="0.8" Duration="00:00:1.0"
Storyboard.TargetName="eliTurnPoint"
Storyboard.TargetProperty="Opacity" >
</DoubleAnimation>
</Storyboard>
<Storyboard x:Name="sbColse">
<DoubleAnimation From="0.8" To="0.0" Duration="00:00:1.0"
Storyboard.TargetName="eliTurnPoint"
Storyboard.TargetProperty="Opacity" >
</DoubleAnimation>
</Storyboard>
</Canvas.Resources>
<Ellipse Name="eliTurnPoint" Width="8" Height="8" Fill="Green" Opacity="0.8"
MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
MouseLeftButtonUp="Canvas_MouseLeftButtonUp"
MouseMove="Canvas_MouseMove"
></Ellipse>
</Canvas>
</UserControl>
轉(zhuǎn)折點是動態(tài)增加到規(guī)則類中的,轉(zhuǎn)折點向外暴露兩個事件。
l 轉(zhuǎn)折點拖拽移動事件:當轉(zhuǎn)折點被鼠標拖拽移動時,需要重新設(shè)置規(guī)則的直線坐標點。
l 轉(zhuǎn)折點雙擊事件:當雙擊轉(zhuǎn)折點時,需要重新設(shè)定規(guī)則的直線坐標,自動對其線段。
轉(zhuǎn)折點包含兩個重要的屬性:
l Radius:轉(zhuǎn)折點圖形的半徑。
l CenterPosition:轉(zhuǎn)折點的中心坐標(相對Canvas的坐標 )。
下面是轉(zhuǎn)折點類的代碼:

Code
public partial class RuleTurnPoint : UserControl
{
public delegate void RuleTurnPointMoveDelegate(object sender, MouseEventArgs e, Point newPoint);
public delegate void DoubleClickDelegate(object sender, EventArgs e);
public event RuleTurnPointMoveDelegate RuleTurnPointMove;
public RuleTurnPoint()
{
InitializeComponent();
_doubleClickTimer = new System.Windows.Threading.DispatcherTimer();
_doubleClickTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
_doubleClickTimer.Tick += new EventHandler(_doubleClickTimer_Tick);
}
void _doubleClickTimer_Tick(object sender, EventArgs e)
{
_doubleClickTimer.Stop();
}
public Brush Fill
{
get
{
return eliTurnPoint.Fill;
}
set
{
eliTurnPoint.Fill = value;
}
}
public void ShowDisplayAutomation()
{
sbDisplay.Begin();
}
public void ShowCloseAutomation()
{
sbColse.Begin();
}
private void Canvas_MouseEnter(object sender, MouseEventArgs e)
{
}
Point mousePosition;
bool trackingMouseMove = false;
bool hadActualMove = false;
System.Windows.Threading.DispatcherTimer _doubleClickTimer;
public event DoubleClickDelegate OnDoubleClick;
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (_doubleClickTimer.IsEnabled)
{
_doubleClickTimer.Stop();
if (OnDoubleClick != null)
OnDoubleClick(this, e);
}
else
{
_doubleClickTimer.Start();
FrameworkElement element = sender as FrameworkElement;
mousePosition = e.GetPosition(null);
trackingMouseMove = true;
hadActualMove = false;
if (null != element)
{
element.CaptureMouse();
element.Cursor = Cursors.Hand;
}
}
}
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
FrameworkElement element = sender as FrameworkElement;
hadActualMove = false;
trackingMouseMove = false;
element.ReleaseMouseCapture();
mousePosition = e.GetPosition(null);
element.Cursor = null;
}
public double Radius
{
get
{
return eliTurnPoint.Width / 2;
}
}
public Point CenterPosition {
get
{
return new Point((double)this.GetValue(Canvas.LeftProperty) + Radius, (double)this.GetValue(Canvas.TopProperty) + Radius);
}
set
{
this.SetValue(Canvas.LeftProperty, value.X - Radius);
this.SetValue(Canvas.TopProperty, value.Y - Radius);
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (trackingMouseMove)
{
FrameworkElement element = sender as FrameworkElement;
element.Cursor = Cursors.Hand;
if (e.GetPosition(null) == mousePosition)
return;
hadActualMove = true;
double deltaV = e.GetPosition(null).Y - mousePosition.Y;
double deltaH = e.GetPosition(null).X - mousePosition.X;
double newTop = deltaV + CenterPosition.Y;
double newLeft = deltaH + CenterPosition.X;
Point p = new Point(newLeft, newTop);
CenterPosition = p;
if (RuleTurnPointMove != null)
{
RuleTurnPointMove(sender, e,p);
}
mousePosition = e.GetPosition(null);
}
}
}
對于選中的活動,可以按照下面4種方式對齊:
l 向左對齊:選中活動的X坐標設(shè)置為其中X坐標最小的值。
l 向右對齊:選中活動的X坐標設(shè)置為其中X坐標最大的值。
l 向上對齊:選中活動的Y坐標設(shè)置為其中X坐標最小的值。
l 向下對齊:選中活動的Y坐標設(shè)置為其中X坐標最大的值。
為了需要兩次遍歷選中的活動集合。第一次遍歷取得其中X/Y坐標的最小/最大值,第二次遍歷設(shè)置活動的X/Y坐標為最小/最大值。
代碼如下所示:

Code
public void AlignTop()
{
if (CurrentSelectedControlCollection == null || CurrentSelectedControlCollection.Count == 0)
return;
Activity a = null;
double minY = 100000.0;
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
if (a.CenterPoint.Y < minY)
minY = a.CenterPoint.Y;
}
}
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
a.CenterPoint = new Point(a.CenterPoint.X, minY);
}
}
}
public void AlignBottom()
{
if (CurrentSelectedControlCollection == null || CurrentSelectedControlCollection.Count == 0)
return;
Activity a = null;
double maxY = 0;
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
if (a.CenterPoint.Y >maxY)
maxY = a.CenterPoint.Y;
}
}
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
a.CenterPoint = new Point(a.CenterPoint.X, maxY);
}
}
}
public void AlignLeft()
{
if (CurrentSelectedControlCollection == null || CurrentSelectedControlCollection.Count == 0)
return;
Activity a = null;
double minX = 100000.0;
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
if (a.CenterPoint.X < minX)
minX = a.CenterPoint.X;
}
}
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
a.CenterPoint = new Point(minX, a.CenterPoint.Y);
}
}
}
public void AlignRight()
{
if (CurrentSelectedControlCollection == null || CurrentSelectedControlCollection.Count == 0)
return;
Activity a = null;
double maxX = 0;
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
if (a.CenterPoint.X > maxX)
maxX = a.CenterPoint.X;
}
}
for (int i = 0; i < CurrentSelectedControlCollection.Count; i++)
{
if (CurrentSelectedControlCollection[i] is Activity)
{
a = CurrentSelectedControlCollection[i] as Activity;
a.CenterPoint = new Point(maxX, a.CenterPoint.Y);
}
}
}