WPF PropertyGrid a lokalizace   zodpovězená otázka

WPF

Dobrý den,

měl bych dotaz, mám z WPFToolkitExtended v projektu přidaný propertygrid. Kterému předávám objekt.

Pokud tak udělám názvy vlastností v propertygridu jsou stejné jako názvy vlastností v objektu. To je pro mě nežádoucí a chtěl bych je měnit.

Protože jsem až do teď nikdy nepracoval s touto komponentou ani z WinForms. Tak nemám tušení jak na to.

Zkoušel jsem při předání objektu toto:


PropertyGrid1.SelectedObject = MujObjekt

for each p as PropertyItem in Propertygrid1.properties
   select case p.name
      case "Name"
         p.name = My.Resources.MujObjektName
   end select
next

Tohle funguje, ale jen z části. Nejdou upravit i jiné vlastnosti propertyitemu, protože jsou readonly (př. description).

Určitě by to šlo nějak lépe, ale nevím kde se chytit.

Jo a v atributech vlastnosti v mujObjekt se nelze odkazovat na Resources - to by jinak bylo řešení.

<DisplayName(my.resources.......)> ... nejde

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To není triviální problém ani ve Windows Forms:

http://www.codeproject.com/KB/miscctrl/g...

(<DisplayName(My.Resources.String1)> samozřejmě nejde, to by bylo příliš jednoduché).

Vzhledem k tomu, jak kreténsky má WPF vyřešenou lokalizaci, tak to zcela jistě půjde nějak extrémně krkolomně.

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Děkuji za odpověď,

Ve WPF resp. WPFToolkitExtended má propertygrid asi chybku, protože když nastavím atribut DisplayName vlastnosti tak se mi v propertygridu stejně ukazuje Name (ne displayName).

Takže ani postup který jste mi dal nebude fungovat.

Nicméně jsem ho vyzkoušel a propertydescriptor třídy ukazoval všechno jak měl (lokalizované).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Což možná řeší nová verze WpfToolkitExtended, neměl jsem poslední. Výsledek napíšu po odzkoušení.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak WPFToolkit Extended ve verzi 1.5.0.0 má fungující použitelnou logiku na lokalizaci v propertygridu.

Podle příkladu, který jste poskytl to funguje.

aby to nemusely jiní hledat:

PropertyDescriptor:

Public Class clsGlobaizedPropertyDescriptor
    Inherits PropertyDescriptor

    Private basePropertyDescriptor As PropertyDescriptor
    Private localizedName As String = ""
    Private localizedDescription As String = ""

    ''' <summary>
    ''' Initializes a new instance of the <see cref="clsGlobaizedPropertyDescriptor" /> class.
    ''' </summary>
    ''' <param name="basePropertyDescriptor">The base property descriptor.</param>
    Public Sub New(ByVal basePropertyDescriptor As PropertyDescriptor)
        MyBase.New(basePropertyDescriptor)
        Me.basePropertyDescriptor = basePropertyDescriptor
    End Sub

    ''' <summary>
    ''' Gets the name of the member.
    ''' </summary>
    ''' <returns>The name of the member.</returns>
    Public Overrides ReadOnly Property Name As String
        Get
            Return Me.basePropertyDescriptor.Name
        End Get
    End Property

    ''' <summary>
    ''' Gets the name that can be displayed in a window, such as a Properties window.
    ''' </summary>
    ''' <returns>The name to display for the member.</returns>
    Public Overrides ReadOnly Property DisplayName As String
        Get

            Dim _tableName As String = ""
            Dim _displayName As String = ""

            For Each oAttrib In Me.basePropertyDescriptor.Attributes
                If (oAttrib.GetType().Equals(GetType(clsGlobalizedPropertyAttribute))) Then
                    _displayName = DirectCast(oAttrib, clsGlobalizedPropertyAttribute).Name
                    _tableName = DirectCast(oAttrib, clsGlobalizedPropertyAttribute).Table
                End If
            Next

            'Pokud neexistuje tabulka s resource uvedená v attributu, pak sestaví vlastní název tanulky jako namecpace a class name
            If _tableName.Length = 0 Then _
                _tableName = Me.basePropertyDescriptor.ComponentType.Namespace & "." & Me.basePropertyDescriptor.ComponentType.Name

            'Pokud neexistuje zápis displaname v tabulce resources, pak se použije defaultní
            If _displayName.Length = 0 Then _
                _displayName = Me.basePropertyDescriptor.DisplayName

            'nyní použijeme název tabulky a displayName k přístupu do resources
            Dim rm As ResourceManager = New ResourceManager(_tableName, Me.basePropertyDescriptor.ComponentType.Assembly)

            'vrátí string
            Dim s As String = rm.GetString(_displayName)

            'Pokud není string v tabulce použije se název z basepropertydescriptor
            Return DirectCast(IIf((s Is Nothing), Me.basePropertyDescriptor.Name, s), String)

        End Get
    End Property

    ''' <summary>
    ''' Gets the description of the member, as specified in the <see cref="T:System.ComponentModel.DescriptionAttribute" />.
    ''' </summary>
    ''' <returns>The description of the member. If there is no <see cref="T:System.ComponentModel.DescriptionAttribute" />, the property value is set to the default, which is an empty string ("").</returns>
    Public Overrides ReadOnly Property Description As String
        Get
            Dim _tableName As String = ""
            Dim _descriptionName As String = ""

            For Each oAttrib In Me.basePropertyDescriptor.Attributes
                If (oAttrib.GetType().Equals(GetType(clsGlobalizedPropertyAttribute))) Then
                    _descriptionName = DirectCast(oAttrib, clsGlobalizedPropertyAttribute).Description
                    _tableName = DirectCast(oAttrib, clsGlobalizedPropertyAttribute).Table
                End If
            Next

            'Pokud neexistuje tabulka s resource uvedená v attributu, pak sestaví vlastní název tanulky jako namecpace a class name
            If _tableName.Length = 0 Then _
                _tableName = Me.basePropertyDescriptor.ComponentType.Namespace & "." & Me.basePropertyDescriptor.ComponentType.Name

            'Pokud neexistuje zápis displaname v tabulce resources, pak se použije defaultní
            If _descriptionName.Length = 0 Then _
                _descriptionName = Me.basePropertyDescriptor.DisplayName

            'nyní použijeme název tabulky a displayName k přístupu do resources
            Dim rm As ResourceManager = New ResourceManager(_tableName, Me.basePropertyDescriptor.ComponentType.Assembly)

            'vrátí string
            Dim s As String = rm.GetString(_descriptionName)

            'Pokud není string v tabulce použije se název z basepropertydescriptor
            Return DirectCast(IIf((s Is Nothing), Me.basePropertyDescriptor.DisplayName, s), String)
        End Get
    End Property

    ''' <summary>
    ''' When overridden in a derived class, returns whether resetting an object changes its value.
    ''' </summary>
    ''' <param name="component">The component to test for reset capability.</param><returns>
    ''' true if resetting the component changes its value; otherwise, false.
    ''' </returns>
    Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
        Return Me.basePropertyDescriptor.CanResetValue(component)
    End Function

    ''' <summary>
    ''' When overridden in a derived class, gets the type of the component this property is bound to.
    ''' </summary>
    ''' <returns>A <see cref="T:System.Type" /> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)" /> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)" /> methods are invoked, the object specified might be an instance of this type.</returns>
    Public Overrides ReadOnly Property ComponentType As System.Type
        Get
            Return Me.basePropertyDescriptor.ComponentType
        End Get
    End Property

    ''' <summary>
    ''' When overridden in a derived class, gets the current value of the property on a component.
    ''' </summary>
    ''' <param name="component">The component with the property for which to retrieve the value.</param><returns>
    ''' The value of a property for a given component.
    ''' </returns>
    Public Overrides Function GetValue(ByVal component As Object) As Object
        Return Me.basePropertyDescriptor.GetValue(component)
    End Function

    ''' <summary>
    ''' When overridden in a derived class, gets a value indicating whether this property is read-only.
    ''' </summary>
    ''' <returns>true if the property is read-only; otherwise, false.</returns>
    Public Overrides ReadOnly Property IsReadOnly As Boolean
        Get
            Return Me.basePropertyDescriptor.IsReadOnly
        End Get
    End Property

    ''' <summary>
    ''' When overridden in a derived class, gets the type of the property.
    ''' </summary>
    ''' <returns>A <see cref="T:System.Type" /> that represents the type of the property.</returns>
    Public Overrides ReadOnly Property PropertyType As System.Type
        Get
            Return Me.basePropertyDescriptor.PropertyType
        End Get
    End Property

    ''' <summary>
    ''' When overridden in a derived class, resets the value for this property of the component to the default value.
    ''' </summary>
    ''' <param name="component">The component with the property value that is to be reset to the default value.</param>
    Public Overrides Sub ResetValue(ByVal component As Object)
        Me.basePropertyDescriptor.ResetValue(component)
    End Sub

    ''' <summary>
    ''' When overridden in a derived class, sets the value of the component to a different value.
    ''' </summary>
    ''' <param name="component">The component with the property value that is to be set.</param>
    ''' <param name="value">The new value.</param>
    Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
        Me.basePropertyDescriptor.SetValue(component, value)
    End Sub

    ''' <summary>
    ''' When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
    ''' </summary>
    ''' <param name="component">The component with the property to be examined for persistence.</param><returns>
    ''' true if the property should be persisted; otherwise, false.
    ''' </returns>
    Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
        Return Me.basePropertyDescriptor.ShouldSerializeValue(component)
    End Function
End Class

Localized Object BaseClass

Public Class clsGlobalizedObject
    Implements ICustomTypeDescriptor

    Private globalizedProps As PropertyDescriptorCollection

    ''' <summary>
    ''' Returns a collection of custom attributes for this instance of a component.
    ''' </summary><returns>
    ''' An <see cref="T:System.ComponentModel.AttributeCollection" /> containing the attributes for this object.
    ''' </returns>
    Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes
        Return TypeDescriptor.GetAttributes(Me, True)
    End Function

    ''' <summary>
    ''' Returns the class name of this instance of a component.
    ''' </summary><returns>
    ''' The class name of the object, or null if the class does not have a name.
    ''' </returns>
    Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName
        Return TypeDescriptor.GetClassName(Me, True)
    End Function

    ''' <summary>
    ''' Returns the name of this instance of a component.
    ''' </summary><returns>
    ''' The name of the object, or null if the object does not have a name.
    ''' </returns>
    Public Function GetComponentName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName
        Return TypeDescriptor.GetComponentName(Me, True)
    End Function

    ''' <summary>
    ''' Returns a type converter for this instance of a component.
    ''' </summary><returns>
    ''' A <see cref="T:System.ComponentModel.TypeConverter" /> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter" /> for this object.
    ''' </returns>
    Public Function GetConverter() As System.ComponentModel.TypeConverter Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter
        Return TypeDescriptor.GetConverter(Me, True)
    End Function

    ''' <summary>
    ''' Returns the default event for this instance of a component.
    ''' </summary><returns>
    ''' An <see cref="T:System.ComponentModel.EventDescriptor" /> that represents the default event for this object, or null if this object does not have events.
    ''' </returns>
    Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent
        Return TypeDescriptor.GetDefaultEvent(Me, True)
    End Function

    ''' <summary>
    ''' Returns the default property for this instance of a component.
    ''' </summary><returns>
    ''' A <see cref="T:System.ComponentModel.PropertyDescriptor" /> that represents the default property for this object, or null if this object does not have properties.
    ''' </returns>
    Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty
        Return TypeDescriptor.GetDefaultProperty(Me, True)
    End Function

    ''' <summary>
    ''' Returns an editor of the specified type for this instance of a component.
    ''' </summary>
    ''' <param name="editorBaseType">A <see cref="T:System.Type" /> that represents the editor for this object.</param><returns>
    ''' An <see cref="T:System.Object" /> of the specified type that is the editor for this object, or null if the editor cannot be found.
    ''' </returns>
    Public Function GetEditor(ByVal editorBaseType As System.Type) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor
        Return TypeDescriptor.GetEditor(Me, editorBaseType, True)
    End Function

    ''' <summary>
    ''' Returns the events for this instance of a component.
    ''' </summary><returns>
    ''' An <see cref="T:System.ComponentModel.EventDescriptorCollection" /> that represents the events for this component instance.
    ''' </returns>
    Public Function GetEvents() As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, True)
    End Function

    ''' <summary>
    ''' Returns the events for this instance of a component using the specified attribute array as a filter.
    ''' </summary>
    ''' <param name="attributes">An array of type <see cref="T:System.Attribute" /> that is used as a filter.</param><returns>
    ''' An <see cref="T:System.ComponentModel.EventDescriptorCollection" /> that represents the filtered events for this component instance.
    ''' </returns>
    Public Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, attributes, True)
    End Function

    ''' <summary>
    ''' Returns the properties for this instance of a component.
    ''' </summary><returns>
    ''' A <see cref="T:System.ComponentModel.PropertyDescriptorCollection" /> that represents the properties for this component instance.
    ''' </returns>
    Public Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties

        If Me.globalizedProps Is Nothing Then

            Dim baseProps As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, True)

            Me.globalizedProps = New PropertyDescriptorCollection(Nothing)

            For Each oProp As PropertyDescriptor In baseProps
                Me.globalizedProps.Add(New clsGlobaizedPropertyDescriptor(oProp))
            Next

        End If

        Return Me.globalizedProps

    End Function

    ''' <summary>
    ''' Returns the properties for this instance of a component using the attribute array as a filter.
    ''' </summary>
    ''' <param name="attributes">An array of type <see cref="T:System.Attribute" /> that is used as a filter.</param><returns>
    ''' A <see cref="T:System.ComponentModel.PropertyDescriptorCollection" /> that represents the filtered properties for this component instance.
    ''' </returns>
    Public Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        If (globalizedProps Is Nothing) Then

            'Získá kolekci všech properties
            Dim baseProps As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, attributes, True)

            'vytvoření instance kolekce vlastností
            Me.globalizedProps = New PropertyDescriptorCollection(Nothing)

            'vytvoření kolekce globalizovaných propertydescriptors z původmních vlastností
            For Each oProp As PropertyDescriptor In baseProps
                Me.globalizedProps.Add(New clsGlobaizedPropertyDescriptor(oProp))
            Next

        End If

        Return Me.globalizedProps

    End Function

    ''' <summary>
    ''' Returns an object that contains the property described by the specified property descriptor.
    ''' </summary>
    ''' <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor" /> that represents the property whose owner is to be found.</param><returns>
    ''' An <see cref="T:System.Object" /> that represents the owner of the specified property.
    ''' </returns>
    Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner
        Return Me
    End Function
End Class

Attribut

<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=True)> _
Public Class clsGlobalizedPropertyAttribute
    Inherits Attribute

    Private _resourceName As String = ""
    Private _resourceDescription As String = ""
    Private _resourceTable As String = ""

    ''' <summary>
    ''' Initializes a new instance of the <see cref="clsGlobalizedPropertyAttribute" /> class.
    ''' </summary>
    ''' <param name="name">The name.</param>
    Public Sub New(ByVal name As String)
        Me._resourceName = name
    End Sub

    ''' <summary>
    ''' Initializes a new instance of the <see cref="clsGlobalizedPropertyAttribute" /> class.
    ''' </summary>
    ''' <param name="name">The name.</param>
    ''' <param name="desc">The desc.</param>
    Public Sub New(ByVal name As String, ByVal desc As String)
        Me.New(name)
        Me._resourceDescription = desc
    End Sub

    ''' <summary>
    ''' Gets or sets the name.
    ''' </summary>
    ''' <value>
    ''' The name.
    ''' </value>
    Public Property Name As String
        Get
            Return Me._resourceName
        End Get
        Set(ByVal value As String)
            Me._resourceName = value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the description.
    ''' </summary>
    ''' <value>
    ''' The description.
    ''' </value>
    Public Property Description As String
        Get
            Return Me._resourceDescription
        End Get
        Set(ByVal value As String)
            Me._resourceDescription = value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the table.
    ''' </summary>
    ''' <value>
    ''' The table.
    ''' </value>
    Public Property Table As String
        Get
            Return Me._resourceTable
        End Get
        Set(ByVal value As String)
            Me._resourceTable = value
        End Set
    End Property

End Class

V projektu resx soubory:

jeden s názvem třída.resx

a dva lokalizované

třída.en.resx

třída.de.resx

a ve vlasntnosti objektu pak odkaz na názvy v resx

<clsGlobalizedProperty("Name", "NameDesc")> _
public property Name as string
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback