3

(文字列、文字列の) 辞書があり、辞書の値を使用してディレクトリ パスを設定し、キーを使用して各値の説明を設定します。

例:

Value of a random item of my dictionary: "C:\Test"
Key name of that item = "Test folder"

さて、私のアプリケーションでは、説明を表示するか、完全なディレクトリ パスを表示するかを選択するオプションがあり、ここに問題があります...

それを理解するためのいくつかの画像:

1 - ここで、辞書のアイテムを保存/管理します。

ここに画像の説明を入力

2 - このチェックボックスを使用して、辞書のキーまたは辞書の値をコンボボックスに表示できます (次の画像で確認できます)。

ここに画像の説明を入力

3 - 説明チェックボックスがチェックされている場合、説明がコンボボックスに表示され、項目を追加すると、選択したコンボボックステキスト (説明またはフルパス) が追加されます。

ここに画像の説明を入力

4 - ここで、説明のチェックボックスをオフにします。コンボボックスの説明を同等のフルパスに変更したのと同じ方法で、リストビューの説明を変更したいのです (ただし、コンボボックスの名前を変更するために行うことは、リロードすることです)。辞書はアルファベット順にソートされているため...リストビューのサブアイテムで同じことを行う方法がわかりません)

ここに画像の説明を入力

リストビューのサブアイテム テキストは、説明またはフル パスである可能性があることを覚えておいてください。そのため、この変更を両方の方法で検討する必要があります。

...そしてここに私のコードがあります:

(コメントを読んでください)

    ' First of all
    ' "Item.SubItems(2).Text" can be the description or it can be the full path, so I need to do it with both alternatives

    If ListView_Monitor.Items.Count <> 0 Then

        For Each Item As ListViewItem In ListView_Monitor.Items

            If ShowDescriptions Then ' Showdescription is a boolean var to show descriptions or full paths

                ' Description is stored in the "Dictionary.Key"
                ' I don't know how to get the key name of the item

                ' Item.SubItems(2).Text = Directories_SendTo.keys  ... ...
                ' CType(Item.SubItems(2).Text, Directories_SendTo... ...)

            ElseIf Not ShowDescriptions Then ' Don't show descriptions, I will show fullpaths

                ' Fullpath is stored in the "Dictionary.Value"

                ' Remember that "Item.SubItems(2).Text" can be the description or the fullpath
                ' So if "Item.SubItems(2).Text" is the description then this piece of code works, 'cause the dictionary keyname is the same as the description name 
                Item.SubItems(2).Text = Directories_SendTo(Item.SubItems(2).Text)

                ' Here I need an alternative if "Item.SubItems(2).Text" is the directory path and not the description
            End If

        Next

    End If

アップデート:

解決策(今のところ)...

私の質問は、このコードを改善できるかどうかです(おそらくdict内でループしないようにするためです):

        If ListView_Monitor.Items.Count <> 0 Then

            For Each Item As ListViewItem In ListView_Monitor.Items

                If ShowDescriptions Then ' Show descriptions

                    For Each value In Directories_SendTo.Values
                        If value = Item.SubItems(2).Text Then
                            Item.SubItems(2).Text = FindKeyByValue(Directories_SendTo, Item.SubItems(2).Text)
                        End If
                    Next

                ElseIf Not ShowDescriptions Then ' Show fullpaths

                    For Each key In Directories_SendTo.Keys
                        If key = Item.SubItems(2).Text Then
                            Item.SubItems(2).Text = Directories_SendTo(key)
                        End If
                    Next

                End If

            Next

        End If

   Public Function FindKeyByValue(Of TKey, TValue)(dictionary As Dictionary(Of TKey, TValue), value As TValue) As TKey

        For Each pair As KeyValuePair(Of TKey, TValue) In dictionary
            If value.Equals(pair.Value) Then Return pair.Key
        Next

        ' Throw New Exception("The value is not found in the dictionary.")
        Return Nothing
    End Function
4

2 に答える 2

1

これが私のアプリケーションであれば、UI 要素を datagridview に変更して、カスタム クラスを含むコレクションをバインドし、必要に応じて適切な列を非表示または表示できるようにします。

このアプローチにより、現在直面している問題を心配することなく、将来、プロパティ列を簡単に追加できます。また、UI に多くの情報をハードコーディングすることなく、UI を他のプラットフォーム (モバイル、Web) に拡張することもできます。

たとえば、ファイルに関する情報を保持するために、次のクラスとコレクションを作成します。

Public Class FileDetails
    Public Property Index As Integer
    Public Property Description As String = String.Empty
    Public Property FullFileName As String = String.Empty
    Public ReadOnly Property FileName As String
        Get
            If Not String.IsNullOrEmpty(Me.FullFileName) Then
                Return System.IO.Path.GetFileName(Me.FullFileName)
            Else
                Return String.Empty
            End If
        End Get
    End Property
    Public ReadOnly Property Directory As String
        Get
            If Not String.IsNullOrEmpty(Me.FullFileName) Then
                Return System.IO.Path.GetDirectoryName(Me.FullFileName)
            Else
                Return String.Empty
            End If
        End Get
    End Property
End Class

Public Class FileDetailsCollection
    Inherits System.ComponentModel.BindingList(Of FileDetails)

End Class

情報を保持するためにフォーム レベルで宣言するプライベート メンバー変数を次に示します。

Private m_Collection As FileDetailsCollection

このメソッドは、コレクションにいくつかのサンプル データを設定するために使用されます。

Private Sub LoadCollection()
    Dim wIndex As Integer
    m_Collection = New FileDetailsCollection
    For Each sFileName As String In System.IO.Directory.GetFiles("c:\", "*.*")
        Dim oFileDetails As New FileDetails

        oFileDetails.FullFileName = sFileName
        wIndex += 1
        oFileDetails.Index = wIndex
        oFileDetails.Description = "Test " & wIndex.ToString

        m_Collection.Add(oFileDetails)
    Next
End Sub

このメソッドは、表示される列の定義を含む、グリッドの初期構成を実行します。

Private Sub ConfigureGrid()
    With Me.DataGridView1
        .AutoGenerateColumns = False
        .Columns.Add(New DataGridViewTextBoxColumn With {.DataPropertyName = "Index", .Name = .DataPropertyName, .HeaderText = "Index"})
        .Columns.Add(New DataGridViewTextBoxColumn With {.DataPropertyName = "FullFileName", .Name = .DataPropertyName, .HeaderText = "Song"})
        .Columns.Add(New DataGridViewTextBoxColumn With {.DataPropertyName = "Description", .Name = .DataPropertyName, .HeaderText = "Description"})
        .Columns.Add(New DataGridViewTextBoxColumn With {.DataPropertyName = "Directory", .Name = .DataPropertyName, .HeaderText = "Description"})

        .DataSource = m_Collection
    End With
End Sub

このメソッドは、現在のオプションの変更に対して表示される列を構成します (これはチェックボックスと同等です)。

Private Sub ConfigureColumnsForOptionChange()

    With Me.DataGridView1
        .Columns("Description").Visible = CheckBox1.Checked
        .Columns("Directory").Visible = Not CheckBox1.Checked
    End With
End Sub

最後に、初期化とフォームの起動を実行します。

Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    Call LoadCollection()
    Call LoadGrid()
    Call ConfigureColumnsForOptionChange()

End Sub

ユーザーがチェックボックスの値を変更すると、UI が更新されます。

Private Sub CheckBox1_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles CheckBox1.CheckedChanged
    Call ConfigureColumnsForOptionChange()
End Sub
于 2013-07-04T00:39:10.067 に答える
1

使用しているループを改善する方法についての 2 番目の質問に答えるには、大幅に改善することができます。現時点では、リスト ビューに 100 個のアイテムがあり、ディレクトリに 10 個のアイテムがある場合、コードは少なくとも 1000 回ループし、ディレクトリで使用される値と ShowDescriptions かどうかによって、最大 10 回ループする可能性があります。フラグが立っています。

割り当てループに入る前に適切なキーで辞書を作成することで、直接ループを 110 回に減らすことができます。

    If ListView_Monitor.Items.Count <> 0 Then
        Dim DirectoriesByCurrentKey As New Dictionary(Of String, String)

        If ShowDescriptions Then
            ' If we are showing the descriptions, add each of the items to the new collection, keyed by the value
            For Each key In Directories_SendTo.Keys
                Dim Description As String
                Description = Directories_SendTo(key)
                ' We don't know if description is unique, so make sure that we don't get a runtime error if we 
                ' try to add the same description multiple time
                If Not DirectoriesByCurrentKey.ContainsKey(Description) Then
                    DirectoriesByCurrentKey.Add(Description, key)
                End If
            Next
        Else
            ' Just use the current collection
            DirectoriesByCurrentKey = Directories_SendTo
        End If

        For Each Item As ListViewItem In ListView_Monitor.Items
            Dim sDescription As String = ""
            ' Try to find the current description using the current list item description
            If DirectoriesByCurrentKey.TryGetValue(Item.SubItems(2).Text, sDescription) Then
                ' If we found the entry, change the description to what we found
                Item.SubItems(2).Text = sDescription
            End If
        Next
    End If

Description が一意であるかどうかがわからないため、追加する前に新しい辞書に存在するかどうかをテストする必要があることに注意してください。FindKeyByValue は最初の一致で停止するため、これは現在と同じ動作になります。

于 2013-07-04T17:02:47.340 に答える