Silverlight实用窍门系列:17.中心点联动多线的可拖动控件(绘制工程图、拓扑图基础)【附带源码实例】
本节是继上节所讲述的基础上做出一些调整而来,如有疑问可参考上节文章。
在实际项目中可能会遇到绘制各类工程图或者网络拓扑图之类的情况,这类图基本上都是以设备加线的方式连接在一起的。那么一个中心设备连接多个外围设备的展示方式就是本节需要讲述的内容。上节已经讲了如何绘制一个以某点为圆心绘制出多条线,且线和线之间的角度需要相同来组成一个圆的图。在这个图的中心点加一个设备牵动所有的线的中心点的变化同时在外围点也加一个设备。中心设备和外围设备都可以随意拖动。中心设备的拖动牵连所有与中心设备关联的设备拖动。下面请看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;
}
}
}
{
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>
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;
}
}
{
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 下载实例源码: