继续上节《基于Silverlight智能表单设计开发(三)》,在上一节中我对智能表单设计中带锚点的矩形编辑框类(DesignRectangle)和控件尺寸处理类(ResizeHelper)及控件拖动处理类(DragHelper)进行了分析和简单的代码实现。在这一节我主要是将窗体控件(WindowForm)的设计、开发关键点写出来与大家交流、学习。
与以前章节一样,我先把与WindowForm窗体控件相关的类关系图展现给大家看一下,对照下图我对图中所涉及元素做一简要说明:
- ICtr:是指所有控件的接口。如:文本控件、日期控件等等。
- IForm:是指窗体控件的接口,即WindowForm窗体类要实现的接口。
- DesignRectangle:它的实现就不多说了,在上一节中有详细介绍。在本节中通过它实现窗体拖动、改变大小等操作。
- WindowForm:窗体控件,类似与我们常说的Windows窗口。
- CtrType:控件类型的枚举。
- CtrNumber:控件记录实体类,以它为载体记录在WindowForm窗体中各种类型的控件数量。
一、窗体接口(IForm)
窗体接口(IForm)是对窗体类必须要实现的一些方法、属性进行强制定义,目的是便于智能表单设计面板、各种控件的交互调用。本文中虽然涉及ICtr控件接口,但它不是我们的关注点,在下一节中我将对它进行详细的说明。
1、类图(接口)
在下面的类图中DesignPanle代表带锚点的矩形编辑框容器面板属性接口;PressCtrKey代表当前键盘按键属性接口;WorkflowId代表与之相关联的工作流程ID属性接口;GetContent是获取窗体画布的接口;GetMaxNumber是获取指定类型控件最大序号的接口;SetCreatorCtr是把某一控件设置当前窗口下激活状态的接口。
2、代码片段


/// 窗体接口
/// </summary>
{
/// <summary>
/// 唯一标识
/// </summary>
string UniqueID { get ; set ; }
/// <summary>
/// 获取窗体画布
/// </summary>
/// <returns></returns>
Canvas GetContent();
/// <summary>
/// 获取锚点框
/// </summary>
DesignRectangle DesignPanle { get ;}
/// <summary>
/// 获取或设置窗体名称
/// </summary>
string FormName { get ; set ; }
/// <summary>
/// 获取或设置窗体标题
/// </summary>
string FormCaption { get ; set ; }
/// <summary>
/// 设置焦点
/// </summary>
void SetFocus();
/// <summary>
/// 失去焦点
/// </summary>
void LostFocus();
/// <summary>
/// 获取指定控件最大序号
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
int GetMaxNumber(CtrType type);
/// <summary>
/// 获取最大层级序号
/// </summary>
int GetMaxZIndex();
/// <summary>
/// 获取或设置Ctr键
/// </summary>
bool PressCtrKey { get ; set ; }
/// <summary>
/// 业务流程唯一标识
/// </summary>
string WorkflowId { get ; set ; }
}
二、窗体类(WindowForm)
窗体类继承接口IForm,它是所有控件容器,为用户提供界面设计画布,用户可在它的画布上添加、编辑控件。效果图如下:
1、类图
图中大多方法和属性都是IForm接口的实现,它们的定义在IForm中有说明。
2、代码片段
先看窗体类WindowForm界面XAML代码


< Border BorderBrush ="LightGray" BorderThickness ="2" ></ Border >
< Canvas x:Name ="cvsPanle" Margin ="2" ></ Canvas >
</ Grid >
窗体类WindowForm的关键代码:


///在窗体上鼠标左键弹起时是触发的事件方法
/// </summary>
{
ICtr tmpCtr = null ;
if (currentCtrType != CtrType.None)
{
Point curP = e.GetPosition(cvsPanle);
tmpCtr = CreateHelper.CreateCtr( this as IForm, currentCtrType);
tmpCtr.CtrLeft = curP.X;
tmpCtr.CtrTop = curP.Y;
currentCtrType = CtrType.None;
_mainPage.Focus();
}
this .Cursor = Cursors.Arrow;
}
/// <summary>
/// 获取指定控件最大序号
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public int GetMaxNumber(CtrType type)
{
int maxValue = 0 ;
var qs = from q in ctr_Nums where q.ControlType == type select q;
if (qs == null || qs.Count() == 0 )
{
maxValue = 1 ;
ctr_Nums.Add( new CtrNumber() { ControlType = type,Number = maxValue});
}
else
{
qs.Single().Number ++ ;
maxValue = qs.Single().Number;
}
return maxValue;
}
List < Line > gridlines = new List < Line > ();
/// <summary>
/// 画格线的方法
/// </summary>
private void SetGridLines()
{
SolidColorBrush brush = new SolidColorBrush();
brush.Color = Color.FromArgb( 255 , 160 , 160 , 160 );
double thickness = 0.3 ;
double top = 0 ;
double left = 0 ;
double width = cvsPanle.ActualWidth;
double height = cvsPanle.ActualHeight;
if (width <= 0 ) width = 480d;
if (height <= 0 ) height = 480d;
double stepLength = 20 ;
double x, y;
x = left + stepLength;
y = top;
foreach (Line l in gridlines)
{
cvsPanle.Children.Remove(l);
}
gridlines.Clear();
while (x < width + left)
{
Line line = new Line();
line.X1 = x;
line.Y1 = y;
line.X2 = x;
line.Y2 = y + height;
line.SetValue(Canvas.ZIndexProperty, 0 );
line.Stroke = brush;
line.StrokeThickness = thickness;
line.Stretch = Stretch.Fill;
cvsPanle.Children.Insert( 0 , line);
gridlines.Add(line);
x += stepLength;
}
x = left;
y = top + stepLength;
while (y < height + top)
{
Line line = new Line();
line.X1 = x;
line.Y1 = y;
line.X2 = x + width;
line.Y2 = y;
line.SetValue(Canvas.ZIndexProperty, 0 );
line.Stroke = brush;
line.Stretch = Stretch.Fill;
line.StrokeThickness = thickness;
cvsPanle.Children.Insert( 0 ,line);
gridlines.Add(line);
y += stepLength;
}
}
/// <summary>
///在窗体上鼠标左键压下时是触发的事件方法
/// </summary>
private void LayoutRoot_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
_designCtr.SetVisible( true );
ICtr tmpCtr = null ;
foreach (UIElement c in cvsPanle.Children)
{
if ((c as DesignRectangle) == null ) continue ;
tmpCtr = (c as DesignRectangle).GetContentObject() as ICtr;
if (tmpCtr != null ) tmpCtr.LostFocus();
}
}
太晚了,今天分析至此,由于有些内容涉密我能做太多说明,希望朋友们能看明白我的思路,给出宝贵意见。下一节将涉及文本控件、日期控件的设计和开发。