继续上节《基于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>public interface IForm
{
/// <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代码
<Grid x:Name="LayoutRoot" Background="White" Tag="WindowForm" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown" MouseEnter="LayoutRoot_MouseEnter" MouseLeave="LayoutRoot_MouseLeave" MouseLeftButtonUp="LayoutRoot_MouseLeftButtonUp">
<Border BorderBrush="LightGray" BorderThickness="2"></Border>
<Canvas x:Name="cvsPanle" Margin="2"></Canvas>
</Grid>
窗体类WindowForm的关键代码:
/// <summary>
///在窗体上鼠标左键弹起时是触发的事件方法
/// </summary>private void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)private List<CtrNumber> ctr_Nums = new List<CtrNumber>();
{
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();
}
}
太晚了,今天分析至此,由于有些内容涉密我能做太多说明,希望朋友们能看明白我的思路,给出宝贵意见。下一节将涉及文本控件、日期控件的设计和开发。