using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
using System.ComponentModel;
using TCHRS.Web.Utility;
namespace Web.SendArchive
{
public class HMIFactory
{
/// <summary>
/// 每行显示的属性个数
/// </summary>
public int PropertyCountPerRow { get; set; }
/// <summary>
/// 查询事件
/// </summary>
public event EventHandler btnSearch_Event;
/// <summary>
/// 添加事件
/// </summary>
public event EventHandler btnAdd_Event;
/// <summary>
/// 修改事件
/// </summary>
public event EventHandler btnUpdate_Event;
/// <summary>
/// 删除事件
/// </summary>
public event EventHandler btnDelete_Event;
private Page _Loader;
private Panel panel;
private IListSource listDataSource;
private object DataListShow;
/// <summary>
/// 一次性初始化
/// </summary>
static HMIFactory()
{
if (!HMIHelper.DicTypeControl.ContainsKey(typeof(DescriptionAttribute)))
HMIHelper.DicTypeControl.Add(typeof(DescriptionAttribute), () => new Label());
HMIHelper.DicTypeControl.Add(typeof(Delegate), () => new Button());
}
/// <summary>
/// 构造函数 类型为Page类型 其他类型待扩展
/// </summary>
/// <param name="page"></param>
public HMIFactory(Page page)
{
this._Loader = page;
PropertyCountPerRow = 2;
}
private object _DataSource;
/// <summary>
/// 数据源
/// </summary>
public object DataSource
{
get {
return _DataSource;
}
set
{
if (_DataSource != value)
{
_DataSource = value;
_DataSourceType = _DataSource.GetType();
DataBind();
}
}
}
private Type _DataSourceType;
/// <summary>
/// 数据源类型
/// </summary>
public Type DataSourceType
{
get {
if (_DataSourceType==null&&_DataSource != null)
{
_DataSourceType = _DataSource.GetType();
}
return _DataSourceType;
}
set
{
if (_DataSource != value)
{
_DataSourceType = value;
}
}
}
/// <summary>
/// 数据绑定
/// </summary>
public void DataBind()
{
if (_Loader == null || (_DataSource == null && _DataSourceType == null))
return;
AddPanel();
List<ControlTagPair> listPair = GetControlPair();
Table tableLayOut = LayOutControls(listPair);
panel.Controls.Add(tableLayOut);
}
/// <summary>
/// 布局控件
/// </summary>
/// <param name="listPair">控件对,包含一个说明的Label控件和一个实际内容的控件</param>
/// <returns></returns>
private Table LayOutControls(List<ControlTagPair> listPair)
{
Table tableLayOut = new Table();
tableLayOut.Attributes["Width"] = "100%";
TableRow row;
TableCell tcTag;
TableCell tcValue;
row = new TableRow();
for (int p = 0; p < listPair.Count; p++)
{
var pair = listPair[p];
tcTag = new TableCell();
tcTag.CssClass = "left2";
tcTag.Controls.Add(pair.Tag);
tcValue = new TableCell();
tcValue.CssClass = "right2";
tcValue.Width = new Unit(320, UnitType.Pixel);
tcValue.Controls.Add(pair.Value);
row.Cells.Add(tcTag);
row.Cells.Add(tcValue);
if ((p + 1) % PropertyCountPerRow == 0)//换行
{
tableLayOut.Rows.Add(row);
row = new TableRow();
}
}
row = new TableRow();//增加按钮
row.Attributes["align"] = "right";
tcValue = new TableCell();
tcValue.Attributes["Width"] = "100%";
CreateButtons().ForEach(w => tcValue.Controls.Add(w as Control));
row.Cells.Add(tcValue);
tableLayOut.Rows.Add(row);
row = new TableRow();//增加DataGrid
row.Width = new Unit(100, UnitType.Percentage);
tcValue = new TableCell();
DataListShow = new GridView();
BindGridView(DataListShow);
tcValue.Controls.Add(DataListShow as Control);
row.Cells.Add(tcValue);
tableLayOut.Rows.Add(row);
return tableLayOut;
}
/// <summary>
/// 绑定GridView
/// </summary>
/// <param name="gv">需要绑定的GridView</param>
private object BindGridView(object gv)
{
gv.GetType().InvokeMember("DataSource", BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, gv, new object[]{listDataSource});
gv.GetType().InvokeMember("AutoGenerateColumns",BindingFlags.Public|BindingFlags.Instance|BindingFlags.SetProperty,null,gv,new object[]{ true });
gv.GetType().InvokeMember("DataBind", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,null, gv,null);
return gv;
}
/// <summary>
/// 绑定GridView
/// </summary>
/// <param name="gv">需要绑定的GridView</param>
/// <param name="source">数据源</param>
private void BindGridView(GridView gv, IListSource source)
{
gv.DataSource = source;
gv.DataBind();
}
/// <summary>
/// 创建按钮集合
/// </summary>
/// <returns></returns>
private List<IButtonControl> CreateButtons()
{
List<IButtonControl> listButtons = new List<IButtonControl>();
//IButtonControl selectButton = CreateSelectButton();
//listButtons.Add(selectButton);
object inital = DataSourceType.BaseType.GetField("inital", BindingFlags.Public | BindingFlags.Static).GetValue(null);
IButtonControl button;
button = CreateDelegateButton("SelectCompare", typeof(Select<>).MakeGenericType(DataSourceType), new object[] { inital});
listButtons.Add(button);
button = CreateDelegateButton("Delete", typeof(Func<bool>), null);
listButtons.Add(button);
button = CreateDelegateButton("Save", typeof(Func<bool>), null);
listButtons.Add(button);
return listButtons;
}
private delegate List<T> Select<T>(T inital);
/// <summary>
/// 创建查询按钮
/// </summary>
/// <returns></returns>
private IButtonControl CreateSelectButton()
{
MethodInfo select = DataSourceType.BaseType.GetMethod("SelectCompare", new Type[] { DataSourceType });
object inital = DataSourceType.BaseType.GetField("inital", BindingFlags.Public | BindingFlags.Static).GetValue(null);
Delegate selectDelegate = Delegate.CreateDelegate(typeof(Select<>).MakeGenericType(DataSourceType), inital, select, false);
var control = HMIHelper.DicTypeControl[typeof(Delegate)]();
control.ID = "btn" + select.Name;
IButtonControl selectButton = control as Button;//IButtonControl;
string text = select.GetDescription();
selectButton.Text = text;
selectButton.Click += (sender, e) => { listDataSource = selectDelegate.DynamicInvoke(inital) as IListSource; BindGridView(DataListShow); };
return selectButton;
}
/// <summary>
/// 根据方法名创建委托生成相应的控件
/// </summary>
/// <param name="methodName">方法名称</param>
/// <param name="delegateType">委托类型</param>
/// <param name="parameters">参数集合</param>
/// <returns></returns>
private IButtonControl CreateDelegateButton(string methodName, Type delegateType, params object[] parameters)
{
object[] paramObjs ;
paramObjs = parameters ?? new object[] { };
Button button = HMIHelper.DicTypeControl[typeof(Delegate)]() as Button;
MethodInfo method = DataSourceType.BaseType.GetMethod(methodName, paramObjs.Select(w => w.GetType()).ToArray());
var paraReturn = method.ReturnType;
Delegate dlgt ;
if (paramObjs != null && paramObjs.Length > 0)
dlgt = Delegate.CreateDelegate(delegateType, paramObjs.FirstOrDefault(), method, false);
else
dlgt = Delegate.CreateDelegate(delegateType,DataSource, method.Name);
button.ID = "btn" + method.Name;
string text = method.GetDescription();
button.Text = text;
button.Click += (sender, e) => { if (paraReturn == typeof(List<>).MakeGenericType(DataSourceType)) { listDataSource = dlgt.DynamicInvoke(paramObjs.ToArray()) as IListSource; BindGridView(DataListShow); } else dlgt.DynamicInvoke(paramObjs.ToArray()); };
return button;
}
/// <summary>
/// 获取数据源属性控件对集合
/// </summary>
/// <returns></returns>
private List<ControlTagPair> GetControlPair()
{
var properties = GetDataSourceMemeber();
List<ControlTagPair> listPair = new List<ControlTagPair>();
foreach (var p in properties)
{
listPair.Add(GenerateControlAndTag(p));
}
return listPair;
}
/// <summary>
/// 增加Panel Or Div
/// </summary>
private void AddPanel()
{
panel = new Panel();
//panel.ID = "mainBody";
panel.CssClass = "mainBody";
Panel divRight = new Panel();
//divRight.ID = "right";
divRight.CssClass = "right";
string position =DataSource.GetDescription(true,DataSourceType);
divRight.Controls.Add(new global::System.Web.UI.WebControls.Literal{ Text= position}) ;
//divRight.Controls.Add(panel);
//_Loader.Form.Controls.Add(divRight);
_Loader.Form.Controls.Add(AddPanel(divRight, panel));
}
/// <summary>
/// 叠加Panel或Div
/// </summary>
/// <param name="panels">需要按顺序叠加的Panel集合</param>
/// <returns></returns>
private Panel AddPanel(params Panel[] panels)
{
Panel back = new Panel();
if (panels == null || panels.Length <= 0) return new Panel();
back = panels.FirstOrDefault();
panels.Aggregate((pre, next) => { pre.Controls.Add(next); return next; });
return back;
}
/// <summary>
/// 获取数据源的public属性
/// </summary>
/// <returns></returns>
private PropertyInfo[] GetDataSourceMemeber()
{
Type type = this.DataSourceType;
if (type == null) return null;
//var properties = type.GetProperties(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static);
var properties = FilerChildProperties(type).ToArray();
return properties;
}
/// <summary>
/// 过滤父类属性 只获取子类的public属性
/// </summary>
/// <param name="type">需要过滤的类型</param>
/// <returns></returns>
public List<PropertyInfo> FilerChildProperties(Type type)
{
List<PropertyInfo> listProperties = new List<PropertyInfo>();
var childAndParent = type.GetProperties();
var parent = type.BaseType.GetProperties();
List<PropertyInfo> listChildAndParent = new List<PropertyInfo>();
listChildAndParent.AddRange(childAndParent);
List<PropertyInfo> listParent = new List<PropertyInfo>();
listParent.AddRange(parent);
foreach (var p in listParent)
{
listChildAndParent.Remove(listChildAndParent.FirstOrDefault(w => w.Name == p.Name));
}
listProperties = listChildAndParent;
return listProperties;
}
/// <summary>
/// 获取描述特性的描述信息
/// </summary>
/// <param name="property">属性信息</param>
/// <returns></returns>
public string GetDescription(PropertyInfo property)
{
string back = string.Empty;
if (!property.IsDefined(typeof(DescriptionAttribute), true))
return back;
var descriptions = property.GetCustomAttributes(typeof(DescriptionAttribute), true);
foreach (var des in descriptions)
{
back += (des as DescriptionAttribute).Description+",";
}
return back.TrimEnd(',');
}
//public string GetEnumDescription(Enum obj)
//{
// string back = string.Empty;
// var attrs = TypeDescriptor.GetAttributes(obj.GetType());
// DescriptionAttribute da = attrs[typeof(DescriptionAttribute)] as DescriptionAttribute;
// if (da != null)
// back = da.Description;
// return back;
//}
/// <summary>
/// 生成属性对应的控件
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
public Control GenenrateControls(PropertyInfo property)
{
Control ctrl =null;
if (HMIHelper.DicTypeControl.ContainsKey(property.PropertyType))
ctrl = HMIHelper.DicTypeControl[property.PropertyType]() ?? new TextBox();
ctrl = new TextBox();
var value = property.GetValue(DataSource, null);
if (property.PropertyType.IsEnum)
{
ctrl = new DropDownList();
var source = GetEnumDictionary(value);
if (!Enum.IsDefined(property.PropertyType, value)&&!object.Equals(value,Activator.CreateInstance( property.PropertyType)))
{
ctrl = new CheckBoxList();
(ctrl as CheckBoxList).RepeatDirection = RepeatDirection.Horizontal;
}
if (source.Keys.Count == 2)
{
ctrl = new RadioButtonList();
(ctrl as RadioButtonList).RepeatDirection = RepeatDirection.Horizontal;
}
var listCtrl = (ctrl as ListControl);
listCtrl.DataSource = GetEnumDictionary(value);
listCtrl.DataValueField = "key";
listCtrl.DataTextField = "value";
listCtrl.DataBind();
if (!Enum.IsDefined(property.PropertyType, value)&&!(ctrl is RadioButtonList||ctrl is CheckBoxList))
listCtrl.Items.Insert(0,new ListItem(""));
}
ctrl.ID = property.Name;
return ctrl;
}
/// <summary>
/// 获取枚举类型的及其对应值的描述特性的描述信息
/// </summary>
/// <param name="enumSource">源枚举类型</param>
/// <returns></returns>
public Dictionary<int, string> GetEnumDictionary(object enumSource)
{
Dictionary<int, string> dicBack = new Dictionary<int, string>();
var type = enumSource.GetType();
var values = Enum.GetValues(type);
foreach(int i in values)
{
string name = Enum.GetName(type, i);
string discription = (Enum.Parse(type,name) as Enum ).GetDescription();//GetEnumDescription(type.GetField(name));
dicBack.Add(i, discription ?? name);
}
return dicBack;
}
/// <summary>
/// 生成控件和标签对
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
public ControlTagPair GenerateControlAndTag(PropertyInfo property)
{
ControlTagPair pair = new ControlTagPair();
var tag = HMIHelper.DicTypeControl[typeof(DescriptionAttribute)]();
tag.ID = "lbl" + property.Name;
ITextControl tText = tag as ITextControl;
if (tText != null)
tText.Text = GetDescription(property);
if (string.IsNullOrEmpty(tText.Text))
tText.Text = property.Name;
var value = GenenrateControls(property);
//ITextControl vText = value as ITextControl;
//if (vText != null)
// vText.Text = property.GetValue(DataSource, null).ToString();
pair.Tag = tag;
pair.Value = value;
return pair;
}
}
/// <summary>
/// 控件和标签对类
/// </summary>
public class ControlTagPair
{
public Control Tag;
public Control Value;
public ControlTagPair()
{
Tag = new Label();
Value = new TextBox();
}
public ControlTagPair(Control value)
{
Value = value;
}
public ControlTagPair(Control tag,Control value)
{
Tag = tag;
Value = value;
}
}
}