自动设置的类,版本2,在设计上比前一个版本有进步。

class     Base

Imports System.Windows.Forms
Imports System.Xml
Imports System.IO
Imports System.Reflection
Imports System.ComponentModel
Public Class Base

#Region "公共构造"
    Public Sub New()

    End Sub
    Public Sub New(ByVal Frm As Form)
        Me.FromMain = Frm
    End Sub
#End Region

#Region "受保护有属性或变量"
    Protected md_SavePaln As New ArrayList
    Protected md_ConfigPath As String = Application.StartupPath & "\Lily.Config.Xml"
    Protected Enum EnumMode
        保存
        加载
    End Enum
    Protected md_FrmMain As Form
    '获取控件所在的容器
    Protected ReadOnly Property GetParents(ByVal Control As Control) As ArrayList
        Get
            '获取控件所在的容器
            Dim ary As New ArrayList
            While Not Control.Parent Is Nothing
                ary.Add(Control.Parent)
                Control = Control.Parent
            End While
            Return ary
        End Get
    End Property
#End Region

#Region "受保护的方法"

    '检查指定的控件是否允许保存,如果没有指定。默认保存窗体上所有可以保存的控件
    Protected Overridable Function IsSaveControl(ByVal Control As Control) As Boolean
        '判断控件是否是指定容器的子控件
        Dim ctr As Control
        For Each ctr In Me.md_SavePaln
            If ctr.Contains(Control) Then
                Return False
            End If
        Next

        If Me.md_CheckControl Is Nothing Then
            Return True
        End If

        Return Me.md_CheckControl.Contains(Control)
    End Function

    '返回指定的容器,是否允许保存指定的属性
    Protected Overridable Function IsSavePanel(ByVal Control As Control) As Boolean
        '默认不保存容器
        Return False
    End Function

    '遍历窗体上所有的控件
    Protected Sub FromControls(ByVal Control As Control)
        '获取窗体上所有控件
        Dim Ctr As Control
        Dim strerror As String = String.Empty
        For Each Ctr In Control.Controls
            If Ctr.Controls.Count = 0 Then
                If IsSaveControl(Ctr) Then
                    If Me.md_EnumMode = EnumMode.保存 Then
                        Me.ReflectionSaveValue(Ctr)
                    Else
                        Me.RefectionGetValue(Ctr)
                    End If
                End If
            Else
                '这是一个容器,确认是否有属性进行保存
                If Me.IsSavePanel(Ctr) Then
                    '容器
                    If IsSaveControl(Ctr) Then
                        If Me.md_EnumMode = EnumMode.保存 Then
                            Me.ReflectionSaveValue(Ctr)
                        Else
                            Me.RefectionGetValue(Ctr)
                        End If
                    End If
                End If


                Me.FromControls(Ctr)
            End If
        Next
        If Control.Controls.Count = 0 Then
            If Me.md_EnumMode = EnumMode.保存 Then
                Me.ReflectionSaveValue(Ctr)
            Else
                Me.RefectionGetValue(Ctr)
            End If
        End If
    End Sub

 

    '读取控件已保存的值
    Protected Overridable Overloads Sub GetValue(ByVal Control As Object)
        '加载指定控件类型的值
        Return
    End Sub

    '调用控件保存过程
    Protected Overridable Overloads Sub SaveValue(ByVal Control As Object)
        '保存指定控件类型的值
        Return
    End Sub

    '保存Xml
    Protected Overridable Function Save(ByVal Control As Control, ByVal Key As String, ByVal Value As Object) As Boolean

        If Control.Name = String.Empty Then
            Return False
        End If

        Try
            Dim ary As ArrayList = Me.GetParents(Control)
            Dim doc As XmlDocument = New XmlDocument

            '判断文件是否存在
            If Not File.Exists(Me.md_ConfigPath) Then
                Dim xmlData As String = "<Config></Config>"
                doc.Load(New StringReader(xmlData))
            Else
                doc.Load(Me.md_ConfigPath)
            End If

            Dim i As Int32
            Dim elem2 As XmlElement, elem As XmlElement
            Dim RootName As String = ary(ary.Count - 1).name
            elem = doc.DocumentElement.SelectSingleNode(RootName)
            '判断指定名称的节点是否已存在
            If elem Is Nothing Then
                elem = doc.CreateElement(RootName)
                elem = doc.DocumentElement.AppendChild(elem)
            End If

            If ary.Count > 0 Then
                For i = ary.Count - 1 To 0 Step -1
                    ' Create a new element and add it to the document.
                    Dim childName As String = ary(i).name
                    '判断节点是否已存在
                    elem2 = elem.SelectSingleNode(childName)
                    If elem2 Is Nothing Then
                        elem2 = doc.CreateElement(childName)
                        elem2 = elem.AppendChild(elem2)
                    End If
                    elem = elem2


                    '属性节点
                    Dim propertyElem As Xml.XmlElement
                    '判断是否是控件的父对象
                    If Control.Parent Is ary(i) Then
                        elem2 = elem.SelectSingleNode(Control.Name)
                        '根据控件名称判断xml是否存在有此节点
                        If elem2 Is Nothing Then
                            '不存在根据控件名称创建此节点
                            elem2 = doc.CreateElement(Control.Name)
                            '创建要保存的属性名称节点
                            propertyElem = doc.CreateElement(Key)
                            '属性节点是控件名称节点的子
                            elem2.AppendChild(propertyElem)
                            '控件名称节点是父对象的子
                            elem.AppendChild(elem2)
                        Else
                            '属性名称节点是否存在
                            propertyElem = elem2.SelectSingleNode(Key)
                            If propertyElem Is Nothing Then
                                '创建要保存的属性名称节点
                                propertyElem = doc.CreateElement(Key)
                                '属性节点是控件名称节点的子
                                elem2.AppendChild(propertyElem)
                            End If
                        End If
                        '此处存在有问题,对于几一个控件,只能设置一个属性
                        '设置节点的值
                        propertyElem.InnerText = Value
                    End If
                Next
            End If
            '保存到Xml
            doc.Save(Me.md_ConfigPath)
            Return True
        Catch ex As Exception
            Me.md_LastErrorMessage = ex.Message
            Return False
        End Try
    End Function

    '加载XML
    Protected Overridable Function Load(ByVal Control As Control, ByVal Key As String) As Object
        If Control.Name = String.Empty Then
            Return Nothing
        End If

        Try
            Dim ary As ArrayList = Me.GetParents(Control)
            Dim doc As XmlDocument = New XmlDocument

            If Not File.Exists(Me.md_ConfigPath) Then
                Return Nothing
            Else
                doc.Load(Me.md_ConfigPath)
            End If

            Dim i As Int32
            Dim elem2 As XmlElement, elem As XmlElement
            Dim RootName As String = ary(ary.Count - 1).name
            elem = doc.DocumentElement.SelectSingleNode(RootName)
            '判断指定名称的节点是否已存在
            If elem Is Nothing Then
                Return Nothing
            End If

            If ary.Count > 0 Then
                For i = ary.Count - 1 To 0 Step -1
                    ' Create a new element and add it to the document.
                    Dim childName As String = ary(i).name
                    '判断节点是否已存在
                    elem2 = elem.SelectSingleNode(childName)
                    If Not elem2 Is Nothing Then elem = elem2

                    '属性节点
                    Dim propertyElem As Xml.XmlElement
                    '判断是否是控件的父对象
                    If Control.Parent Is ary(i) Then
                        '判断控件节点是否存在
                        elem2 = elem.SelectSingleNode(Control.Name)
                        If Not elem2 Is Nothing Then
                            '判断属性节点是否存在
                            propertyElem = elem2.SelectSingleNode(Key)
                            If Not propertyElem Is Nothing Then
                                '属性名称节点存在
                                '判断用户是否指定了属性名称
                                Return propertyElem.InnerText
                            End If
                        End If
                    End If
                Next
            End If
        Catch ex As Exception
            Me.md_LastErrorMessage = ex.Message
            Return Nothing
        End Try
    End Function


#End Region

#Region "私有属性或变量"
    Private md_EnumMode As EnumMode
    '最后一次错误信息
    Private md_LastErrorMessage As String = String.Empty
#End Region

#Region "私有方法"
    Private Sub ReflectionSaveValue(ByVal Control As Control)
        Dim Type() As Type = {Control.GetType}
        Dim Method As Reflection.MethodInfo = Me.GetType.GetMethod("SaveValue", BindingFlags.Instance Or BindingFlags.InvokeMethod Or BindingFlags.NonPublic, Nothing, CallingConventions.Any, Type, Nothing)
        Dim Arg() As Object = {Control}
        If Method Is Nothing Then
            Return
        Else
            Method.Invoke(Me, Arg)
        End If
    End Sub

    Private Sub RefectionGetValue(ByVal Control As Control)
        Dim Type() As Type = {Control.GetType}
        Dim Method As Reflection.MethodInfo = Me.GetType.GetMethod("GetValue", BindingFlags.Instance Or BindingFlags.InvokeMethod Or BindingFlags.NonPublic, Nothing, CallingConventions.Any, Type, Nothing)
        Dim Arg() As Object = {Control}
        If Method Is Nothing Then
            Return
        Else
            Method.Invoke(Me, Arg)
        End If
    End Sub

    Private Sub FormClosing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
        '当窗体保存时,保存控件的值

        If Me.md_FrmMain Is Nothing Then
        Else
            Me.md_EnumMode = EnumMode.保存
            Me.FromControls(Me.md_FrmMain)
        End If

    End Sub

    '绑定窗体关闭事件
    Private Sub BindClosingHandler()
        AddHandler md_FrmMain.Closing, AddressOf Me.FormClosing
    End Sub

#End Region

#Region "公共方法"
    Public Sub LoadValue()
        If Me.md_FrmMain Is Nothing Then
            Throw New System.Exception("没有指定要加载设置的窗体。")
        End If
        '加载上次保存的值
        Me.md_EnumMode = EnumMode.加载
        Me.FromControls(Me.md_FrmMain)
    End Sub
    Public Sub LoadValue(ByVal Control As Control)
        If Me.md_FrmMain Is Nothing Then
            Throw New System.Exception("没有指定要加载设置的窗体。")
        End If
        Me.RefectionGetValue(Control)
    End Sub
#End Region

#Region "公共属性"
    Private md_CheckControl As ArrayList
    <Description("返回或设置要进行保存的控件。为Nothing保存窗体上所有可以保存的控件。")> _
        Public Property CheckControl() As ArrayList
        Get
            Return Me.md_CheckControl
        End Get
        Set(ByVal Value As ArrayList)
            Me.md_CheckControl = Value
        End Set
    End Property
    <Description("返回最后一次错误信息。 ")> _
    Public ReadOnly Property LastErrorMessage() As String
        Get
            Return Me.md_LastErrorMessage
        End Get
    End Property
    <Description("返回或设置要进行保存的窗体。")> _
    Public Property FromMain() As Form
        Get
            Return Me.md_FrmMain
        End Get
        Set(ByVal Value As Form)
            Me.md_FrmMain = Value
            '绑定窗体事件
            BindClosingHandler()
        End Set
    End Property
#End Region

End Class



'记录程序的设置值
Imports System.IO
Imports System.Xml
Imports System.Windows.Forms
Imports System.Reflection
Public Class WindowsControl
    Inherits Base
    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal Frm As Form)
        MyBase.New(Frm)
    End Sub

#Region "TextBox"
    Protected Overridable Overloads Sub GetValue(ByVal Control As TextBox)
        Dim Value As String = Me.Load(Control, "Text")
        If Value Is Nothing Then
        Else
            Control.Text = Value
        End If
    End Sub
    Protected Overridable Overloads Sub SaveValue(ByVal Control As TextBox)
        Me.Save(Control, "Text", Control.Text)
    End Sub
#End Region

#Region "ComboBox"
    Protected Overridable Overloads Sub GetValue(ByVal Control As ComboBox)
        Dim Value As String = Me.Load(Control, "Text")
        If Value Is Nothing Then
        Else
            Control.Text = Value
        End If
    End Sub
    Protected Overridable Overloads Sub SaveValue(ByVal Control As ComboBox)
        Me.Save(Control, "Text", Control.Text)
    End Sub
#End Region

#Region "CheckBox"
    Protected Overridable Overloads Sub GetValue(ByVal Control As CheckBox)
        Dim Value As Object = Me.Load(Control, "Checked")
        If Value Is Nothing Then
        Else
            Control.Checked = CType(Value, Boolean)
        End If
    End Sub

    Protected Overridable Overloads Sub SaveValue(ByVal Control As CheckBox)
        Dim Value As Int32 = CType(Control.Checked, Int32)
        Me.Save(Control, "Checked", Value)
    End Sub
#End Region

#Region "RadioButton"
    Protected Overridable Overloads Sub GetValue(ByVal Control As RadioButton)
        Dim Value As Object = Me.Load(Control, "Checked")
        If Value Is Nothing Then
        Else
            Control.Checked = CType(Value, Boolean)
        End If
    End Sub

    Protected Overridable Overloads Sub SaveValue(ByVal Control As RadioButton)
        Dim Value As Int32 = CType(Control.Checked, Int32)
        Me.Save(Control, "Checked", Value)
    End Sub
#End Region

#Region "DateTimePicker"
    Protected Overridable Overloads Sub GetValue(ByVal Control As DateTimePicker)
        Dim Value As Object = Me.Load(Control, "Value")
        If Value Is Nothing Then

        Else
            If IsDate(Value) Then
                Control.Value = CType(Value, Date)
            End If
        End If
    End Sub

    Protected Overridable Overloads Sub SaveValue(ByVal Control As DateTimePicker)
        Dim Value As Date = Control.Value
        Me.Save(Control, "Value", Value)
    End Sub
#End Region

#Region "Splitter"
    Protected Overridable Overloads Sub GetValue(ByVal Control As Splitter)
        Dim Value As Integer = Val(Me.Load(Control, "SplitPosition"))

        If Value > 0 Then
            Control.SplitPosition = Value
        End If

    End Sub

    Protected Overridable Overloads Sub SaveValue(ByVal Control As Splitter)
        Dim Value As Integer = Control.SplitPosition
        Me.Save(Control, "SplitPosition", Value)
    End Sub
#End Region

End Class



---调用
'自定义保存组件
Public Class clsUserSaveSetting
    Inherits Lily.Tools.SaveSetting.WindowsControl
    '重写基本保存ComboBox的方法
    Protected Overloads Overrides Sub GetValue(ByVal Control As System.Windows.Forms.ComboBox)
        Dim Value As Object
        Dim Count As Int32 = Val(Me.Load(Control, "Count"))

        Dim i As Int32
        For i = 0 To Count
            Value = Me.Load(Control, "Item" & i)
            If Value Is Nothing Then
            Else
                Control.Items.Add(Value)
            End If
        Next

        Value = Me.Load(Control, "Text")
        If Value Is Nothing Then
        Else
            Control.Text = Value
        End If
    End Sub

    Protected Overloads Overrides Sub SaveValue(ByVal Control As System.Windows.Forms.ComboBox)
        '保存当前文本框的值
        Me.Save(Control, "Text", Control.Text)
        Dim i As Int32
        '保存Items
        For i = 0 To Control.Items.Count - 1
            Dim Key As String = "Item" & i
            Dim Value As String = Control.Items(i).ToString
            Me.Save(Control, Key, Value)
        Next
        '保存个数
        Me.Save(Control, "Count", Control.Items.Count)
    End Sub

    Public Sub New()
        MyBase.New()
        Me.md_ConfigPath = Application.StartupPath & "\cfg.xml"
    End Sub
    Public Sub New(ByVal frm As Form)
        MyBase.New(frm)
        Me.md_ConfigPath = Application.StartupPath & "\cfg.xml"
    End Sub


    '保存TreeTable的列宽
    Protected Overloads Sub GetValue(ByVal Control As Lily.TreeTable91)
        Dim i As Int32
        For i = 0 To Control.Cols.Count - 1
            Dim Value As Int32 = Val(Me.Load(Control, "Col" & i))
            If Value > 0 And Not Control.Cols(i).AutoWidth Then
                Control.Cols(i).Width = Value
            End If
        Next
    End Sub
    Protected Overloads Sub SaveValue(ByVal Control As Lily.TreeTable91)
        Dim i As Int32
        For i = 0 To Control.Cols.Count - 1
            If Not Control.Cols(i).AutoWidth Then
                Me.Save(Control, "Col" & i, Control.Cols(i).Width)
            End If
        Next
    End Sub
    '保存容器类控件这是必须的。
    Protected Overrides Function IsSavePanel(ByVal Control As System.Windows.Forms.Control) As Boolean
        If TypeOf Control Is Lily.TreeTable91 Then
            Return True
        End If
    End Function
End Class


--调用
        Dim a As New clsUserSaveSetting(Me)
        'Dim ary As New ArrayList
        'ary.Add(Me.TreeTable911)
        'ary.Add(Me.TreeTable912)
        'a.CheckControl = ary
        a.LoadValue()


--文档

lily.tools.savesetting.base
受保护方法:
IsSaveControl 判断是否指定了属性[CheckControl],如果指定了只保存已指定的控件.否则保存窗体上所有的控件.可以重写。
IsSavePanel 判断是否保存容器类型控件,默认为False,如果需要保存需要在继承类中重写。
FromControls 遍历窗体上所有的控件。判断控件是否需要保存进行判断,并调用指定控件类型的保存方法或加载方法。
GetValue 调用指定控件类型获取值的方法.
SaveValue 调用保存指定控件类型值的方法
Save 保存到XML
Load 从XML里加载。
受保护属性:
md_SavePaln 保存允许的保存的容器对象
md_ConfigPath 保存值的文件路径。
md_FrmMain 进行操作的窗体.
GetParents 获取指定控件所属的容器直到md_FrmMain
公共方法:
LoadValue 有重载加载值。
公共属性:
CheckControl 返回或设置要进行保存操作的指定控件。
LastErrorMessage 返回最后一次错误信息。
FromMain 返回或设置要进行保存的窗体。
lily.tools.savesetting.WindowsControl[继承于Base]
GetValue 多种控件类型的重载.此类不保存容器类控件,如果需要保存容器类控件,请重写IsSavePanel方法.
SaveValue
   Protected Overridable Overloads Sub GetValue(ByVal Control As TextBox)
        Dim Value As String = Me.Load(Control, "Text")
        If Value Is Nothing Then
        Else
            Control.Text = Value
        End If
    End Sub
    Protected Overridable Overloads Sub SaveValue(ByVal Control As TextBox)
        Me.Save(Control, "Text", Control.Text)
    End Sub

posted on 2005-12-30 22:05  zqonline  阅读(557)  评论(0编辑  收藏  举报

导航