您的位置:首页 > 其它

XAF中的自定义属性编辑器

2010-11-27 12:06 260 查看
转自:http://www.cnblogs.com/lauyee/archive/2010/06/21/1756978.html

XAF是什么,如果您没听说过,本文可能对你没有帮助,但如果你正在查找同样问题的解决方法希望对你有所帮助。(注:所举得例子全部是Web工程下的,Win工程原理相同)

XAF自动从业务类生成UI。自动的根据业务类各属性的类型生成所需的属性编辑器。比如,对于一个业务类中的String型的属性,生成的是一个文本框(从界面看是那样)。对Datetime型的属性生成一个日期选择框。

常用的属性编辑器类见下表(Web工程下):

TpyePropertyEditorType备注
StringDevExpress.ExpressApp.Web.Editors.ASPx.ASPxStringProertyEditor展示文本框
Int32DevExpress.ExpressApp.Web.Editors.ASPx.ASPxIntProertyEditor展示可调整的数字输入框
BooleanDevExpress.ExpressApp.Web.Editors.ASPx.ASPxBooleanProertyEditor选中按钮
DatetimeDevExpress.ExpressApp.Web.Editors.ASPx.ASPxDatetimeProertyEditor时间框
EnumDevExpress.ExpressApp.Web.Editors.ASPx.ASPxEnumProertyEditor下拉框
<BaseObject>DevExpress.ExpressApp.Web.Editors.ASPx.ASPxLookupPropertyEditor下拉框,通常是同这个对象形成一对多的关系
在创建业务类的时候这些对象自动和业务类的属性关联,不需要再做声明。还可以选择其他的属性编辑器。可以在Xafml文件的Application | Views | Items | PropertyEditor节点或Application | Views | Items | PropertyEditor节点找到。如:

与 Rating 属性相应的 Application | Views | Items | PropertyEditor 节点:

view source

print?

<
Application
>
<
Views
>
<
DetailView
ID
=
"Song_DetailView"
>
<
Items
>
<
PropertyEditor
PropertyName
=
"Rating"
PropertyEditorType
=
"MySolution.Module.Web.MySolutionAspNetModule.WebStarRatingPropertyEditor"
/>
</
Items
>
</
DetailView
>
</
Views
>
</
Application
>
与 Rating 属性相应的 Application | BOModel | Class | Member 节点:

view source

print?

<
Application
>
<
Views
>
<
DetailView
ID
=
"Song_DetailView"
>
<
Items
>
<
PropertyEditor
PropertyName
=
"Rating"
PropertyEditorType
=
"MySolution.Module.Web.MySolutionAspNetModule.WebStarRatingPropertyEditor"
/>
</
Items
>
</
DetailView
>
</
Views
>
</
Application
>
当然最好的做法是用可视化的模型编辑器,也是可以在两个节点下找到,如图:





针对属性的类型不同,允许选择的类型不同。上图是字符串类型允许选择的属性编辑器。

所有的属性编辑器都要由PropertyEditor类继承。继承结构是这样的:



要实现一个自定义的属性编辑器,首先要确定从哪一个PropertyEditor的派生类继承,以及要是用的控件。

现在我要做的是:实现一个一对多关系的下拉属性编辑框。下拉框的要实现成树状结构。一开始我打算从ASPxLookupPropertyEditor继承,他是业务类型默认的属性编辑器。但是这一次有点麻烦,ASPxLookupPropertyEditor类包含的控件是ASPxComboBox,ASPxComboBox控件中无法包含一颗树。因为绑定的是一个对象,而不是一个简单的值,所以上述列表中的PropertyEditor的派生类都不适合。这一次我选择继承的是ASPxObjectPropertyEditorBase类。这是对象属性编辑器的基类。ASPxLookupPropertyEditor类就由这个类继承。

因为代码和方法相对比较少,重点只是在于你可能需要在好多个重写的方法中找到合适的那个,所以就不用画类图了。直接贴出代码:(再看代码的时候按所标注释的编号看,那是我完成代码的顺序)

view source

print?

001
[PropertyEditor()]
//为了在上图的模型编辑器中会出现你自定义的编辑器,要加上这句代码。可以有参数,表示编辑器的数据类型。
002
public
class
ASPxTreePropertyEditor :ASPxObjectPropertyEditorBase
003
{
004
005
 
private
WebLookupEditorHelper helper;
006
 
public
ASPxTreePropertyEditor(Type objectType, IModelMemberViewItem model)
007
  
:
base
(objectType, model)
008
 
{
009
  
skipEditModeDataBind =
true
;
010
 
}
011
 
//1、集成了借口之后你需要实现的只有这一个重写方法,目的就在于要返回一个自定义的属性编辑器(也就是一个控件)
012
 
protected
override
WebControl CreateEditModeControlCore()
013
 
{
014
  
return
CreateTreeDropDown();
015
 
}
016
 
TreeDropDown CreateTreeDropDown()
017
 
{
018
  
try
019
  
{
020
//2、具体的控件需要用到一个下拉书的控件,我在另一个类中实现了这个控件。
021
TreeDropDown treeDropDown =
new
TreeDropDown();
022
023
treeDropDown.TreeList.DataSource = helper.CreateListView(CurrentObject).CollectionSource.List;
024
treeDropDown.TreeList.KeyFieldName =
"Oid"
;
025
treeDropDown.TreeList.ParentFieldName =
"Parent!Key"
;
026
treeDropDown.TreeList.ClientInstanceName =
"TreeList"
;
027
treeDropDown.TreeList.Width = Unit.Parse(
"100%"
);
028
treeDropDown.ClientInstanceName =
"DropDownEdit"
;
029
treeDropDown.TreeList.PreviewFieldName =
"Name"
;
030
TreeListTextColumn col =
new
TreeListTextColumn();
031
col.Name =
"Name"
;
032
col.FieldName =
"Name"
;
033
treeDropDown.TreeList.Columns.Add(col);
034
treeDropDown.ReadOnly =
true
;
035
treeDropDown.TreeList.SettingsBehavior.AutoExpandAllNodes =
true
;
036
treeDropDown.TreeList.CustomCallback +=
new
TreeListCustomCallbackEventHandler(TreeList_CustomCallback);
037
return
treeDropDown;
038
  
}
039
  
catch
(Exception e)
040
  
{
041
throw
e;
042
  
}
043
 
}
044
045
 
//7、由于ASPxTreeList没有节点点击时间,所以我用了客户端的点击事件,让他返回一个回调方法。
046
 
void
TreeList_CustomCallback(
object
sender, TreeListCustomCallbackEventArgs e)
047
 
{
048
  
//这里是用户在用户改变选择项的时候,重新为属性赋值。以保存对象。
049
  
((TreeDropDown)Editor).Value = helper.GetObjectByKey(CurrentObject, e.Argument);
050
  
EditValueChangedHandler(sender, EventArgs.Empty);
051
 
}
052
053
 
// 6 、再绑定数据时需要用到一个helper对象,用来创建数据列表
054
 
public
override
void
Setup(ObjectSpace objectSpace, XafApplication application)
055
 
{
056
  
base
.Setup(objectSpace, application);
057
  
if
(MemberInfo.IsPersistent)
058
  
{
059
helper =
new
WebLookupEditorHelper(application, objectSpace, MemberInfo.MemberTypeInfo, Model);
060
  
}
061
  
else
062
  
{
063
helper =
new
WebLookupNonPersistentEditorHelper(application, objectSpace, MemberInfo.MemberTypeInfo, Model);
064
  
}
065
 
}
066
}
067
068
//3、之后我生成了这个类。
069
class
TreeDropDown :DevExpress.Web.ASPxEditors.ASPxDropDownEdit 
070
{
071
 
ASPxTreeList treeList;
072
 
public
ASPxTreeList TreeList
073
 
{
074
  
get
075
  
{
076
return
treeList;
077
  
}
078
 
}
079
080
 
public
TreeDropDown()
081
 
{
082
083
  
treeList =
new
ASPxTreeList();
084
  
//4、在这个类中我需要向他添加一个包含有ASPxTreeList控件的模板,所以要实现一个ITemplate接口
085
  
this
.DropDownWindowTemplate =
new
TreeListTemplate(treeList);
086
 
}
087
 
protected
override
void
OnPreRender(EventArgs e)
088
 
{
089
  
string
script =
@" <script type='text/javascript'>
090
  
function RowClickHandler(s, e) {
091
DropDownEdit.SetKeyValue(e.nodeKey);
092
TreeList.GetNodeValues(e.nodeKey, 'Name', setDropDownText);
093
DropDownEdit.HideDropDown();
094
TreeList.PerformCallback(e.nodeKey);
095
  
}
096
  
function setDropDownText(value) {
097
DropDownEdit.SetText(value)
098
  
}</script>"
;
099
  
this
.RegisterScriptBlock(
""
, script);
100
  
treeList.ClientSideEvents.NodeClick =
"RowClickHandler"
;
101
  
base
.OnPreRender(e);
102
 
}
103
104
 
//5、实现ITemplate接口完成一个模板项
105
 
class
TreeListTemplate :ITemplate 
106
 
{
107
  
ASPxTreeList treeList;
108
  
public
TreeListTemplate(ASPxTreeList treeList)
109
  
{
110
this
.treeList =treeList;
111
  
}
112
  
public
void
InstantiateIn(Control container)
113
  
{
114
container.Controls.Add(treeList);
115
  
}
116
 
}
117
}
可以看得出我写代码的时候不是一气呵成,而是从抽象的顶层,从外到里。你用XAF不得不如此,框架逼着你不得不这样。会后完成的东西就是这样:



最后是打包的源代码下载(我的的是XAF10.1.4版)。我没有提供数据库,你应当知道。那对XAF框架来说是不必要的,他会自动负责生成。可能你需要在下面这个界面输一些数据用于测试。



说明:本文原代码中,用了中文属性名和如上的代码注释,只是为了演示方便,并不代表我的编程风格。另:XAF是商业控件,所有代码演示所用的是官方下载的评估版本。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: