如何在程序运行之间保存/恢复表单和控件?

Posted

技术标签:

【中文标题】如何在程序运行之间保存/恢复表单和控件?【英文标题】:how to save/restore a form and controls between program runs? 【发布时间】:2010-07-07 02:59:30 【问题描述】:

我有一个复杂的表单来允许用户配置我的应用程序。

保存表单状态并在程序下次运行时重新加载的最佳方法是什么。

我的意思是他在列表框中输入的文本,组合/列表/收音机的选定项,复选框是否被选中,等等

【问题讨论】:

我假设您使用的是 WinForms,但我不必猜测。另外,请不要重复标题中的标签。 +1,因为您想帮助我。是的 WinForms。抱歉,您不得不猜测,我现在已经使用 VB 超过 5 个小时 - 总经过的时间 - 有些东西对我来说仍然是新的 ;-)。 @mawg,您能否详细说明一下 - 我将您的问题解读为 “我有一个包含各种配置设置的表单,我希望每次打开表单时都将其预填充为正确的值” 。或者您是在问“我如何保存任何特定表单的当前状态以供下次使用”?您是要保存应用程序配置,还是只是一些会话类型的东西?其他回答者似乎对您的问题的解读与我所做的不同。 我如何保存以备下次使用(+1 要求澄清) 【参考方案1】:

这里有很多人告诉我什么时候保存,但告诉我如何保存的人并不多……

最后我选择了 WritePrivateProfileString()

【讨论】:

【参考方案2】:

您有几个保存输入设置的选项 - 在配置文件中,或在注册表中,可能是数据库(甚至可能是“云”,但我不会去那里)。

您应该让用户在保存设置之前执行特定操作(例如单击应用按钮) - 您不应该只在用户关闭表单时保存设置,因为这最终不是好的用户体验。

如何保留设置完全取决于您 - 您可以将它们保存到直接名称/值对样式的配置文件中,您可能希望在配置文件中使用 XML,或者将它们保存为键和值注册表中的已知位置(或者您可以将名称/值对保存到数据库表中)。

下次运行您的应用程序时,启动任务之一可以是检查设置的已知位置(无论是注册表还是配置文件),然后将它们加载到设置类中。确保您对每个设置都有逻辑默认值,以防它从未设置过,或者由于某种原因您无法将其读回。然后可以将设置类传递给每个表单,以便它应用任何设置相关的,或者它可以是一个静态类(全局可见的单个实例类),以便可以从应用程序的任何位置读取它。

编辑:在阅读您对另一个答案的评论后,这里是另一个选项,稍微高级一些。使用我之前提到的设置类,但也使用绑定 - 您可以将设置对象直接绑定到表单,因此输入的任何值都将直接更新到设置对象中,而无需编写代码来执行此操作(前提是您使用两个方式绑定)。 “流式传输”可以通过将设置对象序列化到文件(或数据库)来实现,我建议您查看XmlSerializer。

【讨论】:

【参考方案3】:

序列化表单。

实现ISerializable,并在可序列化构造函数和 GetObject() 方法中加载/保存您的字段。

OnClosing 中序列化表单。

    /// 
    /// try to obtain the las serialized main form with old data
    MainForm mainForm = DeserializeMainForm("mainForm.data");
    ///
    /// if any old data found, create a new(empty) main form
    if (mainForm == null) mainForm = new MainForm();

    static MainForm DeserializeMainForm(string filePath)
    
        MainForm mf = null;
        FileStream fileStream = null;
        try
        
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            fileStream = new FileStream(filePath, FileMode.Open);
            mf = (MainForm)binaryFormatter.Deserialize(fileStream);
        
        catch  
        finally
        
            if (fileStream != null)
            
                fileStream.Close();
            
        

        return mf;
    

主窗体:

[Serializable]
public partial class MainForm : Form, ISerializable

        protected MainForm(SerializationInfo info, StreamingContext context)
        : this()
    
        if (info == null)
            throw new System.ArgumentNullException("info");

        this.tbxServerIp.Text = info.GetString("server ip");
        this.tbxServerPort.Text = info.GetString("server port");
        this.tbxEventFilter.Text = info.GetString("event filter");
        this.tbxWallId.Text = info.GetString("wallId");

        foreach (Control control in this.Controls)
        
            if (control is EventSender)
            
                EventSender eventSender = (control as EventSender);
                eventSender.LoadFromSerializationInfo(info);
            
           
    

    private void SerializeThis()
    
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        FileStream fileStream = new FileStream("mainForm.data", FileMode.Create);
        try
        
            binaryFormatter.Serialize(fileStream, this);
        
        catch
        
            throw;
        
        finally
        
            fileStream.Close();
        
    

    protected override void OnClosing(CancelEventArgs e)
    
        SerializeThis();
        base.OnClosing(e);
    

【讨论】:

【参考方案4】:
Private Sub frm_Closing (sender as Object, e as CancelEventArgs) Handles MyBase.Closing

   ' save all the values you want'

End Sub

Private Sub frm_Load(sender as Object, e as EventArgs) Handles MyBase.Load

   If SaveSettingsExist Then
      ' restore all the values you want'
   End If

End Sub

【讨论】:

啊,手动 :-( 我希望能够将表单流式传输到文件并再次返回。这样,如果添加、删除或更改任何控件,我必须编写代码并更改两次 【参考方案5】:

我实际上有几个像这样使用的通用例程来保存表单大小/位置和 ListView 列设置。所以我有类似...

Private Sub frm_Closing (sender as Object, e as CancelEventArgs) Handles MyBase.Closing

   SaveFormPos(Me)
   SaveListview(Me, lvuInvoices)

End Sub

Private Sub frm_Load(sender as Object, e as EventArgs) Handles MyBase.Load

   RestoreFormPos(Me)
   RestoreListview(Me, lvuInvoices)

End Sub

Me 参数(用于 Listview 例程)用于为要保存到注册表的值创建一个键。你面前有各种各样的选择。您可以将此功能放入所有表单的基类中,创建 SaveState 类,或简单地将例程粘贴到模块中。您可以将此数据保存到注册表、数据库、文本文件中。你可以有一个通用的例程,在 Controls 集合中搜索文本框、复选框等。

但是,一旦您创建了一组有用的保存例程,您就可以在任何您想要的后续表单中使用它们,因此您只需完成一次艰苦的工作。

【讨论】:

【参考方案6】:

我也同意在创建表单/关闭应用程序时调用LoadSettings/SaveSettings 一组函数。

作为应用程序设置的存储位置,我建议使用Isolated Storage。

此外,根据您在表单上使用的控件,您可以选择以 XML 格式保存它们的状态,然后在下次恢复它。 例如Infragistics 控件提供了这种可能性(例如UltraDockManager、UltraToolbarManager 有一对SaveAsXml/LoadFromXml 功能)。

【讨论】:

【参考方案7】:

您可以以某种方式以隐藏的形式将所有内容保存在隐藏的textbox 中。 当用户点击apply按钮时,自动打开文本文件,让程序逐行读取。

例子:

第 1 行可能是图像的位置 第 2 行可能是文本框的文本 第 3 行可以是程序用来确定 复选框是真还是假

【讨论】:

您只是在转移问题。 OP 现在必须弄清楚如何写入和读取此文本,以及写入和读取文件。

以上是关于如何在程序运行之间保存/恢复表单和控件?的主要内容,如果未能解决你的问题,请参考以下文章

在 xamarin 表单中保存和恢复应用程序状态

如何在 Android 上管理从后台恢复的 Xamarin 表单应用程序?

款式修改窗口,开发调整过窗口格局保存功能,关了窗口重新打开还是按关闭前的格局.

应用程序重新启动 C++ Visual Studio 时保存编辑控件用户输入和恢复的有效方法

如何在表单域中保存和恢复多个值(仅使用前端逻辑)

Windows 窗体应用程序 C# - 在调试模式下运行后选项卡控件项移动位置