Nomatic
不积跬步无以至千里

     继续上节《基于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)
{
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;
}
private List<CtrNumber> ctr_Nums = new List<CtrNumber>();
/// <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();
}
}

 

      太晚了,今天分析至此,由于有些内容涉密我能做太多说明,希望朋友们能看明白我的思路,给出宝贵意见。下一节将涉及文本控件、日期控件的设计和开发。

 

 

 

 

posted on 2010-12-06 23:18  刘其武  阅读(3781)  评论(19编辑  收藏  举报