导航

winform 程序对界面上控件的统一控制【二】组件版

Posted on 2010-02-10 15:38  hhshuai  阅读(3806)  评论(9编辑  收藏  举报

  继上篇文章winform 程序对界面上控件的统一控制【一】(赋值\清空\验证……) ,本篇文章将实现一个同样功能的Component(组件)。

  先看看组件的实现,如下所示:

代码一
public partial class CtrlValidation : Component
    {
        
public CtrlValidation()
        {
            InitializeComponent();
            typeCache 
= new TypeCache();
        }

        
public CtrlValidation(IContainer container)
        {
            container.Add(
this);

            InitializeComponent();
            typeCache 
= new TypeCache();
        }

        TypeCache typeCache;

        List
<RealSailing.UI.Utils.SetControl> ctrlCollect = new List<RealSailing.UI.Utils.SetControl>();
        [Description(
"控件集合")]
        [Editor(
typeof(DropEditor), typeof(UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        
public List<RealSailing.UI.Utils.SetControl> CtrlCollect
        {
            
get
            {
                
return ctrlCollect;
            }
            
set
            {
                ctrlCollect 
= value;
            }
        }

        
private object dataSource;
        [Category(
"CatData"), DefaultValue((string)null), RefreshProperties(RefreshProperties.Repaint),
        Description(
"DataGridDataSourceDescr"), AttributeProvider(typeof(IListSource))]
        
public object DataSource
        {
            
get
            {
                
return this.dataSource;
            }
            
set
            {
                
if (((value != null&& !(value is IList)) && !(value is IListSource))
                {
                    
throw new ArgumentException("BadDataSourceForComplexBinding");
                }
                
if ((this.dataSource == null|| !this.dataSource.Equals(value))
                {
                    
if (((value == null|| (value == Convert.DBNull)) && ((this.DataMember != null&& (this.DataMember.Length != 0)))
                    {
                        
this.dataSource = null;
                        
this.DataMember = "";
                    }
                    
else
                    {
                        
if (value != null)
                        {
                            
this.dataSource = value;
                        }
                    }
                }
            }
        }

        
private string dataMember;
        [DefaultValue((
string)null), Description("DataGridDataMemberDescr"),
        Category(
"CatData"),
        Editor(
"System.Windows.Forms.Design.DataMemberListEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"typeof(UITypeEditor))]
        
public string DataMember
        {
            
get
            {
                
return this.dataMember;
            }
            
set
            {
                
if ((this.dataMember == null|| !this.dataMember.Equals(value))
                {
                    
this.dataMember = value;
                }
            }
        }

        
#region 提供方法
        
/// <summary>
        
/// 必填项是否为空,true表示不为空,FALSE表示为空
        
/// </summary>
        
/// <returns></returns>
        public bool CheckIsNull()
        {
            
foreach (RealSailing.UI.Utils.SetControl ctrl in ctrlCollect)
            {
                
object[] obj = new object[] { ctrl };
                TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                
bool editnull = _process.CheckNull();
                
if (!editnull)
                    
return editnull;
            }
            
return true;
        }
        
/// <summary>
        
/// 输入框的格式是否正确,true表示正确,FALSE表示不正确
        
/// </summary>
        
/// <returns></returns>
        public bool CheckIsFormate()
        {
            
foreach (RealSailing.UI.Utils.SetControl ctrl in ctrlCollect)
            {
                
if (ctrl.ControlName.GetType().Equals(typeof(DevExpress.XtraEditors.TextEdit)))
                {
                    
object[] obj = new object[] { ctrl };
                    TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                    
bool editformate = _process.CheckFormate();
                    
if (!editformate)
                        
return editformate;
                }
            }
            
return true;
        }
        
/// <summary>
        
/// 清空画面
        
/// </summary>
        public void SetCtrlClear()
        {
            ctrlCollect.ForEach(ctrl 
=>
            {
                
object[] obj = new object[] { ctrl };
                TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                _process.SetCtrlClear();
            });
        }
        
/// <summary>
        
/// 设置控件可用状态
        
/// </summary>
        
/// <param name="enable"></param>
        public void SetCtrlEnable(bool enable)
        {
            ctrlCollect.ForEach(ctrl 
=>
            {
                
object[] obj = new object[] { ctrl };
                TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                _process.SetCtrlEnable(enable);
            });
        }
        
/// <summary>
        
/// 设置控件默认值
        
/// </summary>
        public void SetCtrlDefault()
        {
            ctrlCollect.ForEach(ctrl 
=>
            {
                
object[] obj = new object[] { ctrl };
                TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                _process.SetCtrlDefault();
            });
        }
        
/// <summary>
        
/// 清除错误提示信息
        
/// </summary>
        public void ClearErrText()
        {
            ctrlCollect.ForEach(ctrl 
=>
            {
                
object[] obj = new object[] { ctrl };
                TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                _process.ClearErrText();
            });
        }
        
/// <summary>
        
/// 将数据行的值映射到文本编辑框中
        
/// </summary>
        
/// <param name="row"></param>
        public void LoadEditRowToText(DataRow row)
        {
            
if (row != null)
            {
                ctrlCollect.ForEach(ctrl 
=>
                {
                    
object[] obj = new object[] { ctrl };
                    TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                    _process.LoadToText(row);
                });
            }
        }
        
/// <summary>
        
/// 将编辑框中的数据赋给数据行
        
/// </summary>
        
/// <param name="row"></param>
        public void SetCtrlTextToEditRow(DataRow row)
        {
            
if (row != null)
            {
                ctrlCollect.ForEach(ctrl 
=>
                {
                    
object[] obj = new object[] { ctrl };
                    TypeProcess _process 
= TypeFactory.CreateType(ctrl.ControlName.GetType().Name, obj, ctrl.ToString(), typeCache);
                    _process.SetTextToRow(row);
                });
            }
        }
        
#endregion
    }

  在上面的CtrlValidation类型中,提供了三个属性,DataSource和DataMember属性为数据绑定属性,和普通的.net控件一样,绑定到数据对象,不过本例中只能绑定到DataSet,并且需要指定它的DataTable。最为重要的是CtrlCollect属性,其类型为List<RealSailing.UI.Utils.SetControl>,表示控件的集合。并且该属性设置了Editor特性(指定用来更改属性的编辑器。无法继承此类。(MSDN))。并用DropEditor和基类型UITypeEditor初始化EditorAttribute类的新实例。接下来我们看看DropEditor类型,如何的实现:

代码二
/// <summary>
    
/// 可见下拉框属性,下拉框为用户控件
    
/// </summary>
    public class DropEditor : UITypeEditor
    {
        
/// <summary>
        
/// 获取由 EditValue 方法使用的编辑器样式
        
/// </summary>
        
/// <param name="context"></param>
        
/// <returns></returns>
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            
if (context != null && context.Instance != null)
            {
                
return UITypeEditorEditStyle.Modal;
            }
            
return base.GetEditStyle(context);
        }
        
/// <summary>
        
/// 使用指定的服务提供程序和上下文编辑指定对象的值。
        
/// </summary>
        
/// <param name="context">可用于获取附加上下文信息的 ITypeDescriptorContext。</param>
        
/// <param name="provider">IServiceProvider,通过它可能获得编辑服务。</param>
        
/// <param name="value">正在编辑的值的实例。</param>
        
/// <returns>新的对象值。如果该对象的值尚未更改,则这应返回与传递给它的对象相同的对象</returns>
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            
//为 UITypeEditor 提供一个接口,用于显示 Windows 窗体,或者在设计模式下在属性网格控件的下拉区域中显示控件。
            IWindowsFormsEditorService iws = (IWindowsFormsEditorService)provider.GetService(
                
typeof(IWindowsFormsEditorService));

            
if (iws != null)
            {
                
using (FrmChoose UIControl = new FrmChoose(context, (List<RealSailing.UI.Utils.SetControl>)value))
                {
                    
if (iws.ShowDialog(UIControl) == DialogResult.OK)
                    {
                        value 
= UIControl.Value;
                        context.OnComponentChanged();
                    }
                }
            }
            
return value;
        }
    }

  DropEditor继承UITypeEditor(自提供可用于设计值编辑器的基类,这些编辑器可提供用户界面 (UI),用来表示和编辑所支持的数据类型的对象值。(MSDN))类型。并重写GetEditStyle( 获取由 EditValue 方法使用的编辑器样式)和EditValue(使用 GetEditStyle 方法所指示的编辑器样式编辑指定对象的值。)方法,前者返回UITypeEditorEditStyle,得到此编辑器的样式,本例中的选择的是Modal样式,显示一个省略号 (...) 按钮;后者返回object类型,表示编辑对象的值。在EditValue方法中,调用一个窗体FrmChoose,给CtrlValidation中的属性CtrlCollect赋值。再来看看FrmChoose窗体时如何实现的?

代码三
public partial class FrmChoose : Form
    {
        
public FrmChoose()
        {
            InitializeComponent();
        }
        
/// <summary>
        
/// 
        
/// </summary>
        
/// <param name="context"></param>
        
/// <param name="value"></param>
        public FrmChoose(ITypeDescriptorContext context, List<RealSailing.UI.Utils.SetControl> value)
        {
            InitializeComponent();
            
this.SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer | System.Windows.Forms.ControlStyles.UserPaint | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
            
this.BackColor = System.Drawing.SystemColors.Control;
            
if (0 != value.Count)
            {
                control 
= value;
                
foreach (object c in context.Container.Components)
                {
                    
if (c.GetType().BaseType.Equals(typeof(RealSailing.DataSet.BaseDataSet)))
                        FillCombFiled(context, c);
                }
            }
            
else
            {
                RealSailing.UI.Utils.SetControl setControl;
                
foreach (object c in context.Container.Components)
                {                    
                    
if (arrType.Contains(c.GetType()))
                    {
                        setControl 
= new RealSailing.UI.Utils.SetControl
                        {
                            ControlName 
= c,
                            NullAble 
= false,
                            Default 
= null,
                            Formate 
= "",
                            KeyFiled 
= false,
                            FiledName 
= ""
                        };
                        control.Add(setControl);
                    }
                    
else if (c.GetType().BaseType.Equals(typeof(RealSailing.DataSet.BaseDataSet)))
                    {
                        FillCombFiled(context, c);
                    }
                }
            }
            
this.gcSelect.DataSource = control;
        }
        
/// <summary>
        
/// 用数据集中的列填充ComboBoxEdit控件
        
/// </summary>
        
/// <param name="context"></param>
        
/// <param name="c"></param>
        private void FillCombFiled(ITypeDescriptorContext context, object c)
        {
            RealSailing.DataSet.BaseDataSet myDs 
= c as RealSailing.DataSet.BaseDataSet;
            Type t 
= context.Instance.GetType();
            System.Reflection.PropertyInfo p 
= t.GetProperty("DataMember");
            
object obj = p.GetValue(context.Instance, null);
            
string table = obj == null ? "" : obj.ToString();

            
if (myDs != null && !string.IsNullOrEmpty(table))
            {
                DataColumnCollection cols 
= myDs.Tables[table].Columns;
                
if(!cols.Contains(" "))
                    cols.Add(
" "typeof(string));
                combFiled.Items.Clear();
                
foreach (DataColumn col in cols)
                {
                    combFiled.Items.Add(col.ColumnName);
                }
            }
        }
        
/// <summary>
        
/// 验证控件类型
        
/// </summary>
        ArrayList arrType = new ArrayList
        {
            
typeof(DevExpress.XtraEditors.LookUpEdit),
            
typeof(DevExpress.XtraEditors.TextEdit),
            
typeof(DevExpress.XtraEditors.DateEdit),
            
typeof(DevExpress.XtraEditors.ComboBoxEdit),
            
typeof(RealSailing.UI.Common.UCSysParaslkEdit),
            
typeof(RealSailing.UI.Control.TextBoxEx),
            
typeof(RealSailing.UI.Control.MemoEditEx),
            
typeof(RealSailing.UI.Common.UCComboBox),
            
typeof(RealSailing.UI.Control.PopuLookUpedit),
            
typeof(RealSailing.UI.Control.UCTextEdit)
        };
        
/// <summary>
        
/// 控件验证项
        
/// </summary>
        List<RealSailing.UI.Utils.SetControl> control = new List<RealSailing.UI.Utils.SetControl>();       
        
        
/// <summary>
        
/// 设置的值
        
/// </summary>
        public List<RealSailing.UI.Utils.SetControl> Value
        {
            
get
            {
                
return control;
            }
        }

        
private void btnOk_Click(object sender, EventArgs e)
        {
            
this.Refresh();
            
this.Close();
        }

        
private void btnCancel_Click(object sender, EventArgs e)
        {
            
this.Close();            
        }
    }

  说明:

  (1)该窗体上只包括一个GridControl(Devexpress)控件,并且在gridview中添加了一个ComboBoxEdit控件,用于选择该控件所绑定到的字段(前提是给CtrlValidation类型中的DataSource何DataMember属性赋过值,本类型中的FillCombFiled方法会通过反射,获取DataSet中DataTable的列,从而绑定到Gridview中ComboBoxEdit控件的Items属性中)。

  (2)窗体中定义了一个ArrayList类型的arrType,该ArrayList中存放的是控件的类型,表名只对该类型的控件做处理,而其他类型的控件则不作处理。

  (3)在FrmChoose有参构造函数中,会更具组件CtrlValidation的上下文,遍历窗体上的所有控件,并且将控件类型在arrType列表中的控件,添加到控件集合control中。

  实现效果如图1示:

 

                                    图1

  这种的实现方式,比较上篇blog的实现方式,更加的方便。 在窗体设计时,将CtrlValidation组件拖入,便会自动加载需要控制的控件(有arrType列表中的控件类型决定)。在CtrlValidation属性中,设置集合属性CtrlCollect,将会弹出如图1所示的画面。点击确定完成控制属性的设置。再就可以调用该组件另外的8个功能函数。

  本篇blog主要是为了阐述如何开发组件,如何给组件定义可视的属性,并且定义集合属性。但愿我讲清楚了。