【问题标题】:How do I persist RichTextBox data between launches?如何在启动之间保留 RichTextBox 数据?
【发布时间】:2020-05-25 01:47:07
【问题描述】:

您好,我是一名新程序员,感谢来自我另一个问题的人的帮助。通过这种方法关闭和重新打开应用程序时,我设法保留了TextBox 数据:

public Form1()
{
    InitializeComponent();

    InitializeSavedValues();
    textBox1.TextChanged += textBox1_TextChanged;
}

private void InitializeSavedValues()
{
    textBox1.Text = (string)Properties.Settings.Default["TextBoxValue"];
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    Properties.Settings.Default["TextBoxValue"] = ((TextBox)sender).Text;
    Properties.Settings.Default.Save();
}

当我关闭并重新打开表单时,是否有办法让我使用与 RichTextBox 类似的东西?

【问题讨论】:

  • 您好!在继续使用 RTF 之前,请仔细查看我们上次为让您快速开始设置而编写的代码。你注意到它的效率有多低了吗? (我希望你会这样做。)每次你按下一个键它都会写一个磁盘!你能想出几个可靠但不经常保存的好方法吗?对于 RTF,我们将需要这些以及更多。
  • 好吧,我会仔细研究一下。我想我跳得太快了

标签: c# winforms richtextbox


【解决方案1】:

这是您关于saving text box between launches 的 SO 帖子的一个很好的后续问题。我赞成它,因为它涉及很多关键点(如果您一次不学习所有关键点也没关系)。 TextBox 通常包含如此少量的数据,几乎可以在任何地方轻松保存。我们可以改进上述代码,仅在按下 [Enter] 键或 TextBox 失去焦点时保存。

RichTextBox 控件不同。它显示的文档可能非常大。例如,图像(已经很大)存储为文本流(甚至更大)。通常使用 Properties.Settings 来存储它是不切实际的。至于“何时保存”,我们不能依赖 Enter 键,因为它只是将换行符插入到多行控件中。

好消息:对于您询问的所有控件,基本流程是相同的。当我们知道“我们想做什么”但不知道“我们将如何做”时,我们可以制作一个包含 interface 关键字的待办事项列表。

interface IPersistCommon // Things we need our custom control to do.
{
    SaveType SaveType { get; set; } // Possible ways to save
    void Save();                    // Save in the manner selected by SaveType
    void Load();                    // Load in the manner selected by SaveType
}

SaveType 是一个我们 自己编造的枚举。它描述了为我们设计的不同控件存储数据的可能方法。我们必须考虑跨平台(如 WinOS、Android 和 iOS)的容量、速度和可移植性。以下是几种可能性:

enum SaveType
{
    AppProperties,      // Like the textbox code shown above
    WindowsRegisty,     // A traditional method, but Windows Only
    File,               // For example, an RTF file in Local AppData (cross-platform)
    FileDataStore,      // Mobile cross-platform
    FileDataStoreJSON,  // Serialize the object's content AND SETTINGS ('enabled' etc.)
    SQLite              // Mobile platforms also available
}

其余的几乎太容易了!获取一个具有我们想要的大部分功能的控件(在本例中为 RichTextBox),并使用 inheritance 创建一个自定义类,该类添加我们在接口中声明的附加功能。这实际上迫使我们实现我们的待办事项列表要求的所有内容(否则它甚至不会构建)。

class PersistRichTextBox    // Our own class...
    : RichTextBox           // ...that inherits the regular one
    , IPersistCommon        // ... and MUST implement SaveType, Save() and Load()
{ }

使用 Browsable 属性实现 SaveType。

[Browsable(true)]
public SaveType SaveType { get; set; }

...这样它在设计模式下可见:

对于 RichTextBox,将其设置为 SaveType。File 表示当我们实现 Save 方法时,将 RTF 数据存储在 AppData 文件夹中的扩展名为 *.rtf 的文件中:

    public void Save()
    {
        switch (SaveType)
        {
            case SaveType.AppProperties:
                // This would be a concern if the RTF for example
                // holds an image file making it gigantic.
                Properties.Settings.Default[Name] = Rtf;
                Properties.Settings.Default.Save();
                break;
            case SaveType.File:
                File.WriteAllText(FileName, Rtf);
                break;
            case SaveType.FileDataStore:
            case SaveType.FileDataStoreJSON:
            case SaveType.WindowsRegisty:
            case SaveType.SQLite:
            default:
                throw new NotImplementedException("To do!");
        }
        Debug.WriteLine("Saved");
    }

对于 RichTextBox,请从同一文件中加载:

    public void Load()
    {
        if (!DesignMode)
        {
            BeginInit();
            switch (SaveType)
            {
                case SaveType.AppProperties:
                    Rtf = (string)Properties.Settings.Default[Name];
                    break;
                case SaveType.File:
                    if(File.Exists(FileName))
                    {
                        Rtf = File.ReadAllText(FileName);
                    }
                    break;
                case SaveType.FileDataStore:
                case SaveType.FileDataStoreJSON:
                case SaveType.WindowsRegisty:
                case SaveType.SQLite:
                default:
                    throw new NotImplementedException("To do!");
            }
            EndInit();
        }
    }

最后,至于“何时”保存,如果用户粘贴图像或按键,请等待大约一秒钟以查看他们仍在输入。如果间隔超时后没有活动,请执行自动保存。

    protected override void OnTextChanged(EventArgs e)
    {
        // This will pick up Paste operations, too.
        base.OnTextChanged(e);
        if(!_initializing)
        {
            // Restarts a short inactivity WDT and autosaves when done.
            WDT.Stop();
            WDT.Start(); 
        }
    }

    // Timeout has expired since the last change to the document.
    private void WDT_Tick(object sender, EventArgs e)
    {
        WDT.Stop();
        Save();
    }

...哪里...

    public PersistRichTextBox()
    {
        WDT = new Timer();
        WDT.Interval = 1000;
        WDT.Tick += WDT_Tick;
    }
    Timer WDT;

您可以clone 来自我们的 GitHub 存储库的完整工作示例。

【讨论】:

  • 好的,感谢您给我一些关于如何使代码更高效的提示。我会用你的建议来解决它,什么时候或者如果我认为我有一些很好的东西我会回来的!
  • 非常感谢您帮助我!我会仔细研究它,并尽我所能把所有的事情都包起来。
  • 当然!在 SO 和现实生活中有很多人在我的整个编码生涯中为我提供了帮助,我很乐意在可能的情况下传授一点知识。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多