继续上节《基于Silverlight智能表单设计开发(二)》,在上一节中我把智能表单设计中最基本的元素锚点类的关键点进行了分析和简单的设计。在这一节我主要是将编辑控件矩形类(DesignRectangle)和控件尺寸处理类(ResizeHelper)及控件拖动处理类(DragHelper)设计、开发关键点写出来和大家分享。
首先我们看一看以DesignRectangle、ResizeHelper、DragHelper为中心的类关系图,在关系图中Auchor类和AuchorLocation枚举在上一节中有详细介绍。
一、编辑控件矩形类(DesignRectangle)
编辑控件矩形类是一个控件容量类,它是后面所有控件(如:文本控件、下拉框控件)的容器,当控件被选中时编辑控件矩形可见,并带有锚点,这时控件处理可编辑状态,用户可以通过鼠标或键盘拖动控件、改变控件大小、修改控件名称等;当编辑控件矩形不可见时,则控件不能被编辑。
1、类图
在下面的类图中,BCHelper、BLHelper、BRHelper、CLHelper、CRHelper、TCHelper、TLHelper、TRHelper分别代表下中、下左、下右、中左、中右、上中、上左、上右八个锚点,方法GetContentObject是获取编辑控件矩框内的对象(一般都是它所包含的具体控件)。
2、代码片段
先看编辑控件矩形类DesignRectangle界面XAML代码


< Grid.ColumnDefinitions >
< ColumnDefinition Width ="6" ></ ColumnDefinition >
< ColumnDefinition Width ="*" ></ ColumnDefinition >
< ColumnDefinition Width ="6" ></ ColumnDefinition >
</ Grid.ColumnDefinitions >
< Grid.RowDefinitions >
< RowDefinition Height ="6" ></ RowDefinition >
< RowDefinition Height ="*" ></ RowDefinition >
< RowDefinition Height ="6" ></ RowDefinition >
</ Grid.RowDefinitions >
< my:Auchor x:Name ="ancTL" />
< my:Auchor x:Name ="ancTC" Grid.Column ="1" />
< my:Auchor x:Name ="ancTR" Grid.Column ="2" />
< my:Auchor x:Name ="ancBL" Grid.Row ="2" />
< my:Auchor x:Name ="ancBC" Grid.Row ="2" Grid.Column ="1" />
< my:Auchor x:Name ="ancBR" Grid.Row ="2" Grid.Column ="2" />
< my:Auchor x:Name ="ancCL" Grid.Row ="1" Grid.Column ="0" />
< my:Auchor x:Name ="ancCR" Grid.Row ="1" Grid.Column ="2" />
< Border x:Name ="brdContent" Grid.Row ="1" Grid.Column ="1" BorderBrush ="#FFB1A08C" BorderThickness ="1.5" ></ Border >
</ Grid >
界面效果图:
控件矩形类DesignRectangle的关键代码:


/// 右上方位尺寸变化帮手
/// </summary>
ResizeHelper TRHelper = new ResizeHelper();
/// <summary>
/// 上中方位尺寸变化帮手
/// </summary>
ResizeHelper TCHelper = new ResizeHelper();
/// <summary>
/// 左上方位尺寸变化帮手
/// </summary>
ResizeHelper TLHelper = new ResizeHelper();
/// <summary>
/// 构造函数
/// </summary>
public DesignRectangle()
{
InitializeComponent();
ancTR.Location = AuchorLocation.上右;
TRHelper.BindResizeFunction(ancTR, this );
ancTC.Location = AuchorLocation.上中;
TCHelper.BindResizeFunction(ancTC, this );
ancTL.Location = AuchorLocation.上左;
TLHelper.BindResizeFunction(ancTL, this );
}
/// <summary>
/// 获取编辑容器中的内容
/// </summary>
/// <returns></returns>
public UIElement GetContentObject()
{
return brdContent.Child as UIElement;
}
二、控件尺寸处理类(ResizeHelper)
ResizeHelper顾名思义可知是用于处理控件大小,在设计中我们将在本项目中所有控件的尺寸编辑都交给这个类来处理。
1、ResizeHelper类图
由下面的类图可知:ResizeHelper只对外公开一个方法BindResizeFunction,这个方法有两个参数,一个是触发鼠标左键按下事件的锚点对象,另一个是需要改变尺寸的主体控件。
2、代码片段


/// 控件尺寸变化处理类
/// </summary>
public class ResizeHelper
{
private Auchor triggerPart;
private DesignRectangle resizePart;
private bool startMoving = false ;
private Point prevMousePos;
/// <summary>
/// 邦定要改变部件大小的方法
/// </summary>
/// <param name="triggerPart"> 触发尺寸改变的部件 </param>
/// <param name="resizePart"> 要尺寸改变的部件 </param>
public void BindResizeFunction(Auchor triggerPart, DesignRectangle resizePart)
{
this .triggerPart = triggerPart;
this .resizePart = resizePart;
ParentCtr = resizePart.Parent as Panel;
this .triggerPart.MouseLeftButtonDown += new MouseButtonEventHandler(triggerPart_MouseLeftButtonDown);
this .triggerPart.MouseLeftButtonUp += new MouseButtonEventHandler(triggerPart_MouseLeftButtonUp);
this .triggerPart.MouseMove += new MouseEventHandler(triggerPart_MouseMove);
}
/// <summary>
/// 移动事件处理方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void triggerPart_MouseMove( object sender, MouseEventArgs e)
{
if ( this .startMoving)
{
ResizeEventArgs args = new ResizeEventArgs();
if (ParentCtr == null ) ParentCtr = resizePart.Parent as Panel;
Point curMousePos = e.GetPosition(ParentCtr);
args.CurPoint = curMousePos;
args.DragDirection = triggerPart.Location;
if (triggerPart.Location == AuchorLocation.上右)
{
this .resizePart.Width += curMousePos.X - this .prevMousePos.X;
this .resizePart.Height -= curMousePos.Y - this .prevMousePos.Y;
this .resizePart.SetValue(Canvas.TopProperty, ( double ) this .resizePart.GetValue(Canvas.TopProperty) - this .prevMousePos.Y + curMousePos.Y);
}
else if (triggerPart.Location == AuchorLocation.下右)
{
this .resizePart.Width += curMousePos.X - this .prevMousePos.X;
this .resizePart.Height += curMousePos.Y - this .prevMousePos.Y;
}
// 其它方位的锚点算法基本是一样的,省略....
this .prevMousePos = curMousePos;
}
}
/// <summary>
/// 鼠标左键弹起事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void triggerPart_MouseLeftButtonUp( object sender, MouseButtonEventArgs e)
{
if ( this .startMoving)
{
this .triggerPart.ReleaseMouseCapture();
this .startMoving = false ;
}
e.Handled = true ;
}
/// <summary>
/// 鼠标左键按下事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void triggerPart_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
if ( ! this .startMoving)
{
if (ParentCtr == null ) ParentCtr = resizePart.Parent as Panel;
this .startMoving = true ;
this .triggerPart.CaptureMouse();
prevMousePos = e.GetPosition(ParentCtr);
}
e.Handled = true ;
}
}
三、控件拖动处理类(DragHelper)
此类主要用于处理处于编辑状态控件位置问题,就是控件的移动操作。通过DragHelper类可以实现被编辑控件鼠标拖动,以及通过点击键盘上的方向键也可以移动控件。
控件拖动处理类(DragHelper)与控件尺寸处理类(ResizeHelper)基本雷同,因此我只将它们的差异代码贴出来供大家参考,类图就省掉了。


/// 邦定要拖动的部件的方法
/// </summary>
/// <param name="triggerPart"> 触发拖动的部件 </param>
/// <param name="movePart"> 要拖动的部件 </param>
public void BindMoveFunction(UIElement triggerPart, DesignRectangle movePart)
{
this .triggerPart = triggerPart;
this .movePart = movePart;
ParentCtr = movePart.Parent as Panel;
this .triggerPart.MouseLeftButtonDown += new MouseButtonEventHandler(triggerPart_MouseLeftButtonDown);
this .triggerPart.MouseLeftButtonUp += new MouseButtonEventHandler(triggerPart_MouseLeftButtonUp);
this .triggerPart.MouseMove += new MouseEventHandler(triggerPart_MouseMove);
}
/// <summary>
/// 移动事件处理方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void triggerPart_MouseMove( object sender, MouseEventArgs e)
{
if ( this .startMoving)
{
Point curMousePos = e.GetPosition(ParentCtr);
if ( ! CheckDrag(curMousePos)) return ;
this .movePart.SetValue(Canvas.LeftProperty,
( double ) this .movePart.GetValue(Canvas.LeftProperty) + curMousePos.X - this .prevMousePos.X);
this .movePart.SetValue(Canvas.TopProperty,
( double ) this .movePart.GetValue(Canvas.TopProperty) + curMousePos.Y - this .prevMousePos.Y);
this .prevMousePos = curMousePos;
}
}
今天就将编辑控件矩形类(DesignRectangle)和控件尺寸处理类(ResizeHelper)及控件拖动处理类(DragHelper)分析至此,下一节将涉及窗体控件(WinForm)的分析、设计。