自动设置的类,版本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 |