将可选的KeyValuePair列表与默认列表合并(覆盖重复键)

时间:2014-01-14 15:26:05

标签: vb.net list key-value

我有一个RichTextBox表格,根据某些标准,它应该输出不同风格的文字。

为了尝试完成此操作,我创建了一个小Class ProgressUpdate,它应该接受要输出的文本,但将其余内容保留为可选项。

我的主要问题是如何从Args获取值并将它们分配给相应的属性?

此外,我不确定这是否是做这类事情的最佳方式,所以如果有人知道更好的方法,我愿意接受建议。感谢。

到目前为止,我的代码现已在@Neolisk的帮助下更新 -

Imports System.Collections.Generic
Imports System.Drawing
Imports System.Reflection

Public Class ProgressUpdate

    Public Property Text As String = ""
    Public Property FontFamily As String = "Calibri"
    Public Property FontSize As Integer = 9
    Public Property FontStyle As FontStyle = FontStyle.Regular
    Public Property Colour As Color = Color.Black

    '**
    ' Constructor
    '*
    Public Sub New(Optional ByVal Text As String = "",
                   Optional ByVal Args As Dictionary(Of String, Object) = Nothing)

        Me.Text = Text

        '** Set the property values from the Args *'
        Dim Type As Type = Me.GetType()
        For Each PropertyName As String In Args.Keys
            Dim PropertyInfo = Type.GetProperty(PropertyName)
            If PropertyInfo IsNot Nothing Then
                PropertyInfo.SetValue(Me, Args(PropertyName), Nothing)
            End If
        Next

    End Sub

End Class

3 个答案:

答案 0 :(得分:1)

您正在寻找Dictionary课程。 List很乐意为您存储等效对象。 Dictionary使用了KeyValuePair,但您可以使用这样的简单赋值替换Key(不允许使用重复的键):

dictionary("FontFamily") = "Calibri"

编辑:关于您现在的主要问题(我看到您刚刚更改为使用词典),您需要使用反射。这是a good answer on that。或者甚至可能this one(语法在大脑上更容易)。实际上,最后一个很好,我将在这里发布:

Dim type As Type = target.GetType();
For Each propName As String In Defaults.Keys
  Dim prop As PropertyInfo = type.GetProperty(propName);
  prop.SetValue(target, Defaults(propName), Nothing);
Next

target是你的对象,它将获得默认值,很可能是你控件中的一个控件。

答案 1 :(得分:1)

根据评论和更好地理解背景,我现在提出以下建议:

Public Class ProgressUpdate

    Public Property Text As String = ""
    Public Property FontFamily As String = "Calibri"
    Public Property FontSize As Integer = 9
    Public Property FontStyle As FontStyle = FontStyle.Regular
    Public Property Colour As Color = Color.Black

    Public Sub New(ByVal text As String)
        Me.Text = text
    End Sub

End Class

像这样使用:

Dim progressUpdate as New ProgressUpdate("Beginning profile restoration...")
progressUpdate.FontStyle = FontStyle.Bold
' set other properties similarly
Me.bw.ReportProgress(0, progressUpdate)

答案 2 :(得分:1)

经过多次辛苦劳作和测试后,我终于想出了一个有效的解决方案。

最初我在寻找一种简单地从传递的Object中自动设置类的所有属性的方法。我希望他们将这组属性与String一起传递给更新RichTextBox的函数,使用属性来格式化要附加的文本。

然而,很明显这不起作用,因为RichTextBox的许多属性都是read-only(例如Bold)。

所以我决定通过我想要的设置并将RichTextBox全部更新为一个,所有工作现在由ProgressUpdate类完成。

感谢@Neolisk和@AaronPalmer与我交谈。我重申这个问题不是100%明确/准确,但你试图以任何方式提供帮助,我感激不尽。

以下是我将如何使用ProgressUpdate类 -

的示例
Class aForm

    Private Property ProgressUpdate As ProgressUpdate

    Public Sub New()
        Me.ProgressUpdate = New ProgressUpdate(Me.CurrentProgressTextbox)
    End Sub

    Private Sub SettingsButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SettingsButton.Click
        Call Me.ProgressUpdate.Update("Clicked Settings...")
    End Sub

    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles CancelButton.Click
        Call Me.ProgressUpdate.Update({{"Text", "You cancelled!!!"}, {"FontStyle", FontStyle.Bold}, {"FontSize", 12.0}})
    End Sub

End Class

这是班级本身 -

Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms

Public Class ProgressUpdate

    Private Property TextBox As RichTextBox
    Private Property Args As Dictionary(Of String, Object)
    Private Property Font As Font

    '**
    ' Constructor
    '*
    Public Sub New(ByVal TextBox As RichTextBox)
        Me.Textbox = TextBox
    End Sub

    '**
    ' Update 'TextBox' with the desired text and style
    '
    ' @param RawArgs Object The Args to use when updating the Textbox (can be either String or Array)
    ' @param Append Boolean Whether or not the Append the Text (Text is overwritten if False)
    '*
    Public Sub Update(Optional ByVal RawArgs As Object = Nothing,
                      Optional ByVal Append As Boolean = True)

        '** Set up Args and ensure that they are valid *'
        Call Me.SetArgs(RawArgs)
        If Me.Args Is Nothing Then Exit Sub

        '** Make sure that Text is declared and set the Text property *'
        Dim Value As Object = Nothing
        If Not Me.Args.TryGetValue("Text", Value) Then Exit Sub
        Dim Text As String = CType(Value, String)

        Call Me.SetFont()   ' Set up the Font to use for the text that is being added

        With Me.TextBox

            If Append Then ' Text is being appended
                If .Text <> "" Then Text = Environment.NewLine & Text ' Add a new line before the Text if necessary
                .AppendText(Text)
            Else ' Text is being overwirtten
                .Text = Text
            End If

            .Select(.GetFirstCharIndexOfCurrentLine(), Text.Length) ' Select all of the last line
            .SelectionFont = Me.Font                                ' Set the desired font
            .Select(.GetFirstCharIndexOfCurrentLine(), 0)           ' Select the current line, with a length of 0
            .ScrollToCaret()                                        ' Scroll to the caret (to show the bottom line)

        End With

    End Sub

    '**
    ' Set the Args property
    '
    ' @param required RawArgs Object    The Args to use when updating the Textbox (can be either String or Array)
    '*
    Private Sub SetArgs(ByVal RawArgs As Object)

        If TypeOf RawArgs Is String Then    ' e.UserState is a String, so it's just the Text that should be added to Args
            Me.Args = New Dictionary(Of String, Object) From {{"Text", RawArgs}}

        ElseIf TypeOf RawArgs Is Array Then ' e.UserState is an Array, so add all of the key/value pairs to Args
            Me.Args = New Dictionary(Of String, Object)
            For KeyIndex As Integer = 0 To UBound(RawArgs)
                Me.Args.Add(RawArgs(KeyIndex, 0), RawArgs(KeyIndex, 1))
            Next

        Else : Me.Args = Nothing   ' There were no Args set
        End If

    End Sub

    '**
    ' Set the correct 'Font' for use on the line that is currently being added to the `TextBox`
    '*
    Private Sub SetFont()

        Dim FontFamily As FontFamily = Nothing
        Dim FontSize As Single = 0
        Dim FontStyle As FontStyle = Nothing
        Dim Value As Object

        With Me.TextBox

            Value = Nothing
            If Me.Args.TryGetValue("FontFamily", Value) Then
                If TypeOf Value Is FontFamily Then
                    FontFamily = Value
                Else : FontFamily = .Font.FontFamily
                End If
            Else : FontFamily = .Font.FontFamily
            End If

            Value = Nothing
            If Me.Args.TryGetValue("FontSize", Value) Then
                If IsNumeric(Value) Then
                    FontSize = Value
                Else : FontSize = .Font.Size
                End If
            Else : FontSize = .Font.Size
            End If

            Value = Nothing
            If Me.Args.TryGetValue("FontStyle", Value) Then
                If TypeOf Value Is FontStyle Then
                    FontStyle = Value
                Else : FontStyle = .Font.Style
                End If
            Else : FontStyle = .Font.Style
            End If

        End With

        Me.Font = New Font(FontFamily, FontSize, FontStyle)

    End Sub

End Class