"remember" 过去条目的方法

Method to "remember" past entries

我在 VB 中构建的应用程序的一部分具有终端功能,我想为其添加功能,以便它按时间顺序记住过去的命令,类似于 windows 终端的工作方式。

简而言之,我希望您能够在文本区域获得焦点时按向上箭头,并能够循环浏览之前输入的命令列表。

我有两个关于如何做到这一点的想法:

  1. 一个组合框,当您按下回车键时,它会读取 combobox.text 中的任何内容,无论是新输入的命令还是已选择的旧命令。然后将该命令添加到组合框的项目中,以便您可以向上滚动并再次找到它。

  2. 只是一个文本框,当按下向上箭头时,循环浏览一些存储的队列并相应地设置文本。这将需要第二个队列来记住循环命令并替换它们,对吗?

是否有任何 Visual Basic 的内置结构对此更好,或者是否有更好的方法?

感谢您的帮助。

比队列更好的是数组。该队列只允许顺序访问,并且在您将其出列后,您出列的对象将获得 "lost"。如果你想保存它并且在未来的会话中也有,你可以使用一个文件,比如 cookie 或者我喜欢的东西,也因为为未来的扩展做准备,一个嵌入式数据库,比如 sqlite 或 firebird。第二个是一个非常强大的数据库,如果你想获得一个服务器,一个强大的服务器

听起来您正在寻找最近使用列表之类的东西。

您对 ComboBox 的想法通常可能是正确的做法。使用 TextBox 执行您的建议将在很大程度上导致... ComboBox.

注意事项:

  • 是否区分大小写? FooBar 是否匹配 fooBar
  • 堆栈(或队列)不是正确的工具,因为如果他们使用列表中索引 4 的内容,则没有简单的方法将该项目从 #4 移动到 #1。
  • 要将此与 ComboBox 一起用作 UI 选择器,您需要使用可用作绑定源的内容。

这是一个新生的 MRU class:

Public Class MRUList

    Private myList As BindingList(Of String)

    Public ReadOnly Property DataList As BindingList(Of String)
        Get
            Return myList '.Select(Function(f) f.Value).ToList
        End Get
    End Property

    Private myCapacity As Integer

    Public Sub New(capacity As Integer)
        myCapacity = capacity
        myList = New BindingList(Of String)
    End Sub

    Public Overloads Sub Add(item As String)

        Dim ndx As Integer = IndexOfKey(item)

        If ndx >= 0 Then
            myList.RemoveAt(ndx)
        End If

        myList.Insert(0, item)

        If myList.Count > myCapacity Then
            myList.RemoveAt(myList.Count - 1)
        End If
    End Sub

    ' case insensitive search
    Private Function IndexOfKey(s As String) As Integer

        Return myList.ToList.FindIndex(Function(f) f.Equals(s,
                   StringComparison.InvariantCultureIgnoreCase))

    End Function

End Class
  • 当他们选择一个现有的项目时,它会从原来的位置移到列表的顶部。
  • 不区分大小写,“Able”匹配“ABLE”。但它是区分大小写的:if/when 他们再次 键入 一个项目,它使用新的大小写。因此,如果“ZIggy”在列表中的插槽 3 中,如果他们正确输入“Ziggy”,则旧的将被删除并使用新的。
  • 有一个容量限制器,因此您不会得到长得离谱的列表。当列表变得太长时,旧项目将被删除。
  • 它是从 BindingList(Of String) 构建的,因此您可以将它绑定到 ListboxComboBox

列表管理在幕后相当浪费。每次我们在 myList(0) 处插入一个新项目时,.NET 都必须移动和调整底层数组。理想的集合类型是 LinkedList,但它不能用作绑定源,而且我不怀疑您会存储 1000 多个项目。

用法:

Private myMRU As New MRUList(8)
...
' bind to CBO in form_load:
cboMRU.DataSource = myMRU.DataList

当事物被添加到列表中时,它们将自动出现在列表中。当用户做出 selection

Private Sub cboMRU_Leave(sender As Object, e As EventArgs) Handles cboMRU.Leave
    If cboMRU.Text.Length = 0 Then Exit Sub

    Dim thisCmd As String = cboMRU.Text
    myMRU.Add(thisCmd)
    cboMRU.Text = ""

End Sub

我使用了 Leave 事件,因为他们可以从列表中选择 select 列表中的项目。您的代码不需要做任何检查新项目和现有项目的事情,Add 方法会为您完成。

在左侧,我输入了 4 项,Delta 是最后一项。接下来,我正确地输入了 Able。 class 删除旧的并将新的作为具有新拼写的 MRU 浮动到顶部。

因为这些对您的代码有意义,所以无论它们是什么,都请在事件中使用 thisCmd。对于更复杂的事情,也许他们键入的只是其他东西的键或标记,请在 MRU Class

中使用 BindingList(of TokenItem)