【问题标题】:How to display a custom DisplayMember in a ComboBox of Objects (namely Locales)如何在对象组合框中显示自定义 DisplayMember(即区域设置)
【发布时间】:2021-06-30 10:18:30
【问题描述】:

我设置了以下代码,以在组合框中提供可用于 .NET 的语言环境列表。

Dim CurrencyList As List(Of CultureInfo) = CultureInfo.GetCultures(CultureTypes.SpecificCultures).ToList

cboCurrencyLocale.DataSource = CurrencyList
cboCurrencyLocale.DisplayMember = "DisplayName"
cboCurrencyLocale.ValueMember = "Name"

目前,这会将 ComboBox 控件设置为显示“DisplayName”属性并使用“Name”属性作为值。我想知道是否有办法进行设置,以便 DisplayMember 属性显示“英语(美国)[en-us]”

我尝试将cboCurrencyLocale.DisplayMember 行更改为cboCurrencyLocale.DisplayMember = "DisplayName" * "Name",但组合框仍然只显示基本的“DisplayName”属性。

那么我如何编码这个 ComboBox 来显示一个自定义的 DisplayMember

【问题讨论】:

    标签: vb.net winforms combobox locale


    【解决方案1】:

    使用继承 CultureInfo 的类的示例。

    从 CultureInfo 类继承,您可以添加一个新属性,该属性返回您喜欢的格式的字符串。在这种情况下,将基类的DisplayNameName 属性修补在一起。

    派生类需要提供至少一个与基类的构造器相匹配的构造器。在这种情况下,接受 Integer 值(对应于LCID 属性)的构造函数似乎是合适的。

    您还应该在派生类中覆盖ToString(),以匹配自定义属性返回的值,以防其他地方需要相同的格式,而无法进行数据绑定。

    Private Class MyCultureInfo
        Inherits CultureInfo
    
        Public Sub New(cultureId As Integer)
            MyBase.New(cultureId)
        End Sub
    
        Public Property MyDisplayMember As String = $"{MyBase.DisplayName} [{MyBase.Name}]"
    
        Public Overrides Function ToString() As String
            Return MyDisplayMember
        End Function
    End Class
    

    要构建List(Of MyCultureInfo),初始化一个新列表,将这个类型的集合传递给接受IEnumerable 的构造函数。 本合集来源来自CultureInfo.GetCultures()

    Dim currencyList As New List(Of MyCultureInfo)(
        CultureInfo.GetCultures(CultureTypes.SpecificCultures).
        OrderBy(Function(d) d.DisplayName).
        Select(Function(c) New MyCultureInfo(c.LCID))
    )
    
    cboCurrencyLocale.DataSource = Nothing
    cboCurrencyLocale.DisplayMember = "MyDisplayName"
    cboCurrencyLocale.ValueMember = "Name"
    cboCurrencyLocale.DataSource = currencyList
    

    【讨论】:

    • 我很好奇一件事,你为什么要把数据源设置为空?
    • 在指定新数据源之前,DataSource 始终明确设置为 null。这将清除内部缓冲区并重置 DisplayMember。如您所见,我以正确的顺序设置控件的属性:DisplayMember、ValueMember,然后是 DataSource。这是internal procedure 所期望的序列。如果您不遵循此模式,它将在内部强制执行,并带有扭曲。当您在 DisplayMember 之前设置 DataSource 时,[...]
    • DisplayMember 被清除,现有的 DataSource 断开并重置,然后新的 DataSource 被连接。之后设置 DisplayMember 时,需要再次断开 DataSource 并再次重置。这可能会发生第三次,当 ValueMember 发生更改时,如果这是在内部确定为基于当前状态的最佳行动方案。为了防止这种情况,您将 DataSource 设置为 null,这会重置 CurrencyManager,然后设置 DisplayMember 和 ValueMember。此时的 DataSource 为 null,因此无需执行任何操作。 [...]
    • 然后给DataSource设置一个有效的DisplayMember,这样操作就只执行一次,而不是两三次。 -- 当 DataSource 没有很多数据要绑定时,你可能不会注意到差异。当您有很多数据要连接到 CurrencyManager 时,情况就不同了。 This can also cause exceptions(参见源代码中的注释)在特定情况下或只是为了按正确顺序执行操作序列而进行大量不必要的工作。
    • 顺便说一句,我已将 OrderBy() 添加到生成 CultureInfo 名称列表的过程中,因为它应该是有序的。 -- 请注意,ComboBox 的每个 Item 都可以作为 MyCultureInfo 和 CultureInfo 对象读取。
    猜你喜欢
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多