本节是继上节所讲述的基础上做出一些调整而来,如有疑问可参考上节文章。
在实际项目中可能会遇到绘制各类工程图或者网络拓扑图之类的情况,这类图基本上都是以设备加线的方式连接在一起的。那么一个中心设备连接多个外围设备的展示方式就是本节需要讲述的内容。上节已经讲了如何绘制一个以某点为圆心绘制出多条线,且线和线之间的角度需要相同来组成一个圆的图。在这个图的中心点加一个设备牵动所有的线的中心点的变化同时在外围点也加一个设备。中心设备和外围设备都可以随意拖动。中心设备的拖动牵连所有与中心设备关联的设备拖动。下面请看Silverlight运行预览图:
在Photoshop里面绘画两个不同颜色的球(绿色和黄色),其直径皆为44像素,保存为Png图片。再在Silverlight项目中添加这两个球的图片。设置黄球图片为中心点,在MainPage.xaml文件中的Canvas下面添加此球图片:
<
Image x:Name
=
"
img1
"
Source
=
"
yellow.png
"
Width
=
"
44
"
Visibility
=
"
Collapsed
"
Canvas.ZIndex
=
"
300
"
Height
=
"
44
"
></
Image
>
设置这个图片可以被拖动,且在拖动的同时让所有的线的起始点始终在这个圆的圆心位置,需要使用行为MouseDragElementBehavior,所以引入Microsoft.Expression.Interactions.dll、Microsoft.Expression.Prototyping.Interactivity.dll和System.Windows.Interactivity.dll。并且在代码也中using Microsoft.Expression.Interactivity.Layout;。此时MainPage.xaml.cs的代码如下:
public
partial
class
MainPage : UserControl
{
public
MainPage()
{
InitializeComponent();
//
让img1图片控件具有MouseDragElementBehavior行为,且为让此控件在拖动过程中执行dragBehavior_Dragging事件。
dragBehavior.Attach(
this
.img1);
dragBehavior.Dragging
+=
new
MouseEventHandler(dragBehavior_Dragging);
//
初始化时默认点击函数
button1_Click(
new
object
(),
new
RoutedEventArgs());
}
MouseDragElementBehavior dragBehavior
=
new
MouseDragElementBehavior();
//
放所有的线的集合
private
List
<
ucLine
>
ucLineList
=
new
List
<
ucLine
>
();
private
void
button1_Click(
object
sender, RoutedEventArgs e)
{
CanvasDevice.Children.Clear();
//
获取需要设置多少条线
double
lineCount
=
double
.Parse((
this
.comboBox1.SelectedItem
as
ComboBoxItem).Content.ToString());
//
获取需要设置的线的长度
double
lineLenth
=
double
.Parse(
this
.textBox1.Text.ToString());
//
设置平均角度
double
angle
=
360.0
/
lineCount;
//
设置线的起始点的坐标
double
centerX
=
250
;
double
centerY
=
250
;
for
(
int
i
=
0
; i
<
lineCount; i
++
)
{
ucLine dline
=
new
ucLine();
//
设置线的半径
dline.R
=
lineLenth;
//
设置线的起始点的坐标
dline.CenterX
=
centerX;
dline.CenterY
=
centerY;
//
设置这根线的角度
dline.AngleAll
=
angle
*
(i);
CanvasDevice.Children.Add(dline);
//
将所有的线添加到线集合中去,以供拖动过程中使用
ucLineList.Add(dline);
}
//
设置img1可见,设置其初始位置。
this
.img1.Visibility
=
Visibility.Visible;
img1.SetValue(Canvas.LeftProperty, centerX
-
22.0
);
img1.SetValue(Canvas.TopProperty, centerY
-
22.0
);
}
///
<summary>
///
img1被拖动的时候触发的事件
///
</summary>
///
<param name="sender"></param>
///
<param name="e"></param>
void
dragBehavior_Dragging(
object
sender, MouseEventArgs e)
{
MouseDragElementBehavior dragBehavior2
=
sender
as
MouseDragElementBehavior;
//
获取到控件被拖动后的位置坐标
double
x1
=
dragBehavior2.X
+
22
;
double
y1
=
dragBehavior2.Y
+
22
;
foreach
(ucLine dline
in
ucLineList)
{
//
设置lineD线的起点坐标为移动后的坐标位置
dline.LineD.X1
=
x1;
dline.LineD.Y1
=
y1;
}
}
}
这些代码是在上一节的基础上进行了一部分的修改,所有的注释都在代码中,需要注意的是比如double x1 = dragBehavior2.X + 22,这里的22这个数字是黄球的半径,是为了让这些线集中在黄球的中心点位置上,而不是集中在黄球的左上角位置。这个是计算的坐标。
中心点设备添加成功了!那么现在该为线的另一点添加绿色球设备,并且让绿色球设备可以被拖动。ucLine.xaml代码中需要添加一句:
<
Image x:Name
=
"
green
"
Source
=
"
green.png
"
Width
=
"
44
"
Canvas.ZIndex
=
"
300
"
Height
=
"
44
"
></
Image
>
ucLine控件的代码页主要是为绿色球添加拖动控件,在拖动的过程中,也要让线的结尾点坐标跟随到拖动的绿色球位置。其ucLine.xaml.cs代码修改如下:
public
partial
class
ucLine : UserControl
{
public
ucLine()
{
InitializeComponent();
dragBehavior.Attach(
this
.green);
dragBehavior.Dragging
+=
new
MouseEventHandler(dragBehavior_Dragging);
}
MouseDragElementBehavior dragBehavior
=
new
MouseDragElementBehavior();
private
double
_R;
private
double
_AngleAll;
private
double
_centerX;
private
double
_centerY;
///
<summary>
///
中心圆半径
///
</summary>
public
double
R
{
get
{
return
_R; }
set
{ _R
=
value; }
}
private
double
_X2;
private
double
_Y2;
///
<summary>
///
指定本控件的X2坐标
///
</summary>
public
double
X2
{
get
{
return
_X2; }
set
{
_X2
=
value;
this
.LineD.X2
=
this
.X2;
}
}
///
<summary>
///
指定本控件的Y2坐标
///
</summary>
public
double
Y2
{
get
{
return
_Y2; }
set
{
_Y2
=
value;
this
.LineD.Y2
=
this
.Y2;
}
}
///
<summary>
///
本控件的中心原点X坐标
///
</summary>
public
double
CenterX
{
get
{
return
_centerX; }
set
{
_centerX
=
value;
this
.LineD.X1
=
_centerX;
}
}
///
<summary>
///
本控件的中心原点Y坐标
///
</summary>
public
double
CenterY
{
get
{
return
_centerY; }
set
{
_centerY
=
value;
this
.LineD.Y1
=
_centerY;
}
}
///
<summary>
///
本控件的起始线弧度
///
</summary>
public
double
AngleAll
{
get
{
return
_AngleAll; }
set
{
_AngleAll
=
value;
//
计算得到角度,然后复制给线的终点坐标位置。注意:设置线终点坐标时须加入线的起点位置
double
sinAngle
=
Math.Sin(
this
.AngleAll
*
Math.PI
/
180
);
double
cosAngle
=
Math.Cos(
this
.AngleAll
*
Math.PI
/
180
);
this
.LineD.X2
=
cosAngle
*
this
.R
+
this
.CenterX;
this
.LineD.Y2
=
this
.CenterY
-
sinAngle
*
this
.R;
//
设置绿色球的坐标位置。
this
.green.SetValue(Canvas.LeftProperty,
this
.LineD.X2
-
22
);
this
.green.SetValue(Canvas.TopProperty,
this
.LineD.Y2
-
22
);
}
}
///
<summary>
///
green被拖动的时候触发的事件
///
</summary>
///
<param name="sender"></param>
///
<param name="e"></param>
void
dragBehavior_Dragging(
object
sender, MouseEventArgs e)
{
MouseDragElementBehavior dragBehavior2
=
sender
as
MouseDragElementBehavior;
double
x1
=
dragBehavior2.X
+
22
;
double
y1
=
dragBehavior2.Y
+
22
;
//
设置本条线的结尾点坐标为拖动后的坐标
this
.LineD.X2
=
x1;
this
.LineD.Y2
=
y1;
}
}
现在所有的动画已经完成,本实例采用VS2010+Silverlight编写,点击 SLLineForYell.rar 下载实例源码: