好久没有更新博客了,有时是有时间没有内容,有时是有内容没有时间。今天则时刚好两者都有了。
最近一段使用Xaf做开发,功能很强大,开发效率很高(在熟练使用的情况下),就不说了。但devexpress12.2中也存在我想要的,但他没有提供的功能,比如我想要一个对列表属性使用类似CheckboxLIst的的多选编辑器,作为查询条件。结果框架没有提供,网上也没有找到现成的,所以只有自己做了。
参考官方文档:http://documentation.devexpress.com/#Xaf/CustomDocument2678,经过两天的折腾,从多条弯路上绕回之后,经历了多重的磨难之后,最后修正了正果:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Templates;
using DevExpress.ExpressApp.Utils;
using DevExpress.ExpressApp.Web.Editors;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
namespace Module.PropertyEditors
{
// 使该编辑器只能在属性是List泛型时可用,但不是默认编辑器
[PropertyEditor(typeof(List<>), false)]
public class PropertyCheckBoxListEditor : WebPropertyEditor
{
public PropertyCheckBoxListEditor(Type objectType, IModelMemberViewItem model) : base(objectType, model)
{
}
// CheckBoxList每行显示数量
private const int NumPerColumn = 2;
private CheckBoxList _checkBoxList;
private Type _listMemberType;
private IList _dataSource;
// 实现本编辑器的创建功能
protected override WebControl CreateEditModeControlCore()
{
_checkBoxList = new CheckBoxList();
_checkBoxList.RepeatDirection = RepeatDirection.Horizontal;
_checkBoxList.RepeatColumns = NumPerColumn;
// 把CheckBoxList放到panel中,panel的属性现在是写死的
Panel panel = new Panel();
panel.Width = Unit.Percentage(100);
panel.Height = Unit.Pixel(60);
panel.ScrollBars = ScrollBars.Auto;
panel.BorderStyle = BorderStyle.Solid;
panel.BorderColor = Color.FromArgb(174,204,240);
panel.BorderWidth = 1;
panel.Controls.Add(_checkBoxList);
// 只对属性类型是以BaseObject的子类为类型的泛型List生效
if (MemberInfo.IsList && MemberInfo.ListElementType.IsSubclassOf(typeof(BaseObject)))
{
_listMemberType = MemberInfo.ListElementType;
// 查询数据,并排序
_dataSource = View.ObjectSpace.GetObjects(_listMemberType);
(_dataSource as XPCollection).Sorting = new SortingCollection() { new SortProperty() { Direction = SortingDirection.Ascending, PropertyName = "DisplayName" } };
_checkBoxList.DataTextField = "DisplayName";
_checkBoxList.DataValueField = "Oid";
}
// // 只对属性类型是以枚举类型的泛型List生效
else if (MemberInfo.IsList && MemberInfo.ListElementType.IsEnum)
{
_listMemberType = MemberInfo.ListElementType;
IList source = new List<KeyValuePair<string, string>>();
// 把枚举类型处理成以枚举与本地化显示为键、值对的列表
foreach (string enumName in _listMemberType.GetEnumNames())
{
source.Add(new KeyValuePair<string,string>(enumName, CaptionHelper.GetLocalizedText("Enums\\" + _listMemberType.FullName, enumName.ToString())));
}
_dataSource = source;
_checkBoxList.DataTextField = "Value";
_checkBoxList.DataValueField = "Key";
}
_checkBoxList.DataSource = _dataSource;
_checkBoxList.DataBind();
// 触发本编辑器值改变的事件
_checkBoxList.SelectedIndexChanged += new EventHandler(EditValueChangedHandler);
return panel;
}
// 要给PropertyValue赋值,否则导致选中任意checkbox后,全不选时显示为最后一次的选择结果
protected override void ReadEditModeValueCore()
{
PropertyValue = SelectValus;
}
// 得到编辑器的值
protected override object GetControlValueCore()
{
return SelectValus;
}
private IList SelectValus
{
get
{
IList list = Activator.CreateInstance(typeof (List<>).MakeGenericType(_listMemberType)) as IList;
foreach (ListItem item in this._checkBoxList.Items)
{
if (item.Selected)
{
if (_listMemberType.IsEnum)
{
if (_dataSource.Cast<KeyValuePair<string, string>>().Any(pair => pair.Key == item.Value))
{
list.Add(Enum.Parse(_listMemberType, item.Value));
}
}
else if (_listMemberType.IsSubclassOf(typeof (BaseObject)))
{
foreach (BaseObject obj in _dataSource)
{
if (obj.Oid.ToString() == item.Value)
{
list.Add(obj);
break;
}
}
}
}
}
return list;
}
}
}
}