PropertyGrid   otázka

VB.NET

Obracím se na zdejší pokročilé s prosbou o radu.

Ve winforms aplikaci používám propertygrid a pátrám po možnosti využít jako prvek pro editaci vlastní vlastnosti typu integer prvek NumericUpDn, kde potřebuji využít také Min a Max vlastnosti a nastavovat je.

Pomocí vlastní třídy poděděné z UITypeEditor se mi povedlo zobrazit numericupdown v dropdown části, ale nedaří se mi dostat prvek přímo do mřížky(griditem) tak aby se změnil přímo vzhled tlačítka na UpDnButton rovnou u griditem a numericupdn se zobrazil přímo v mřížce. Nezkoušel nebo neviděl někde někdo?

Jako druhý dotaz k propertygrid zda-li netušíte lze-li u griditem nějak změnit barvu, nejlépe backcolor nebo barvu fontu forecolor, případně v závislosti na hodnotě dané property?

Předem díky za Vaše reakce.

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

Tohle normálně nejde. A je to i zbytečné dělat, NumericUpDown přímo v mřížce by byl tak malý, že by to bylo neovladatelné. V tomto případě bych udělal obyčejnou validaci po změně hodnoty a případné stornování neplatné hodnoty. Ohledně barvy - rovněž nejde bez těžkého upravení komponenty. Vymýšlíte extrémně komplikované věci s nulovým přínosem.

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

Díky za odpověď.

Mohl byste prosím trochu rozvést tu validaci a stronování.

Nějaké pokusy toho docílit v události PropertyValueChanged mám za sebou, ale property.value je pouze pro čtení a nemohu ji nastavit zpět na OldValue. Bude milé se dozvědět více.

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

Někde si musíte držet ten objekt, který je jako datový zdroj pro PropertyGrid. V případě zadání chybné hodnoty nastavíte jeho příslušnou vlastnost zpátky na OldValue. A nezapomenout zavolat Refresh, jinak se hodnota nepřekreslí.

Public Class Form1
  Dim _n As Number
  Private Sub PropertyGrid1_PropertyValueChanged(s As System.Object, e As System.Windows.Forms.PropertyValueChangedEventArgs) Handles PropertyGrid1.PropertyValueChanged
    Dim number As Integer
    Dim newValue = CStr(e.ChangedItem.Value)
    If Not Integer.TryParse(newValue, number) Then
      MessageBox.Show(String.Format("{0} je neplatná hodnota.", newValue),
                      My.Application.Info.ProductName,
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Error)
      _n.Value = e.OldValue
      PropertyGrid1.Refresh()
    End If
  End Sub
  Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    _n = New Number With {.Value = 123}
    PropertyGrid1.SelectedObject = _n
  End Sub
  Class Number
    Public Property Value As String
  End Class
End Class
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za příklad. Držet data zdroje mě také napadlo,

ale snaha byla se tomu nějak vyhnout a pracovat přímo

s propertygridem. Je dobré vědět, že se někdo vydal

stejnou cestou. Už stačí jen přidat porovnání hodnoty

s vlastnostmi Min a Max.

Pro refresh propertygridu u vlastnosti používám atribut

RefreshProperties(RefreshProperties.All).

...

Mám ještě dotaz ohledně zobrazení objektu osoba(zaměstnanec)

v propertygridu. Mám níže uvedené třídy, zaměstnance zobrazím

v property gridu a mohu po rozbalení editovat samostatně jméno

a příjmení. Zajímá mě, jak docílit možnost upravovat jméno

a příjmení přímo v řádku, kde mi vrací ToString jméno a příjmení

s mezerou podobně jako např. Point, který lze upravovat ve všech

třech řádcích, sloučený s čárkou nebo samostatně.

Nepodařilo se mi najít, jak se s tím vypořádat.

Public Class Person
    Private m_FirstName As String
    <DisplayName("Jméno"), RefreshProperties(RefreshProperties.All), _
    DescriptionAttribute("Jméno")> _
    Public Property FirstName() As String
        Get
            Return m_FirstName
        End Get
        Set(ByVal value As String)
            m_FirstName = value
        End Set
    End Property

    Private m_LastName As String
    <DisplayName("Příjmení"), RefreshProperties(RefreshProperties.All), _
    DescriptionAttribute("Příjmení")> _
    Public Property LastName() As String
        Get
            Return m_LastName
        End Get
        Set(ByVal value As String)
            m_LastName = value
        End Set
    End Property
End Class

Public Class Employee
    Inherits Person

    Private m_BirthDate As Date
    <DisplayName("Datum narozenin"), _
    DescriptionAttribute("")> _
    Public Property Birthdate() As Date
        Get
            Birthdate = m_BirthDate
        End Get
        Set(ByVal value As Date)
            m_BirthDate = value
        End Set
    End Property

        ' Override ToString.
    Public Overrides Function ToString() As String
        Return FirstName & " " & LastName
    End Function

    Public Sub New(ByVal FirstName As String, ByVal LastName As String)
        Me.FirstName = FirstName
        Me.LastName = LastName
    End Sub
End Class
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přesně vím co chcete udělat, ale nikdy jsem to nepotřeboval a nedělal, takže si to budete muset vyzkoušet sám. Postupoval bych tak, že před použitím Google bych spustil .NET Reflector, podíval se na Control.Size, u kterého se to v PropertyGridu zobrazuje složeně jako x, y. Letmým pohledem na implementovaná rozhraní a atributy struktury System.Drawing.Size bych zjistil, že to co potřebuji bude nejspíš spojeno s atributem <TypeConverter(GetType(SizeConverter))> a od toho bych se odpíchnul při hledání Googlem.

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

Díky! ...TypeConverter od toho bych se odpíchnul:

http://www.vb-helper.com/howto_net_type_...

http://www.codeguru.com/columns/vb/artic...

<TypeConverter(GetType(PersonConverter))> _
Public Class Person
    Private m_FirstName As String
    <DisplayName("Jméno"), RefreshProperties(RefreshProperties.All), _
    DescriptionAttribute("Jméno")> _
    Public Property FirstName() As String
        Get
            Return m_FirstName
        End Get
        Set(ByVal value As String)
            m_FirstName = value
        End Set
    End Property

    Private m_LastName As String
    <DisplayName("Příjmení"), RefreshProperties(RefreshProperties.All), _
    DescriptionAttribute("Příjmení")> _
    Public Property LastName() As String
        Get
            Return m_LastName
        End Get
        Set(ByVal value As String)
            m_LastName = value
        End Set
    End Property

    Public Sub New()

    End Sub

    Public Sub New(ByVal FirstName As String, ByVal LastName As String)
        Me.FirstName = FirstName
        Me.LastName = LastName
    End Sub

    Public Overrides Function ToString() As String
        Return FirstName & " " & LastName
    End Function
End Class

Public Class PersonConverter
    Inherits TypeConverter

    Public Overloads Overrides Function _
        CanConvertFrom(ByVal context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        sourceType As System.Type) As Boolean
        If (sourceType.Equals(GetType(String))) Then
            Return True
        Else
            Return MyBase.CanConvertFrom(context, _
                sourceType)
        End If
    End Function

    Public Overloads Overrides Function CanConvertTo(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        destinationType As System.Type) As Boolean
        If (destinationType.Equals(GetType(String))) Then
            Return True
        Else
            Return MyBase.CanConvertTo(context, _
                destinationType)
        End If
    End Function

    Public Overloads Overrides Function ConvertFrom(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        culture As System.Globalization.CultureInfo, ByVal _
        value As Object) As Object
        If (TypeOf value Is String) Then
            Dim txt As String = CType(value, String)
            Dim fields() As String = txt.Split(New Char() _
                {" "})

            Try
                Return New Person(fields(0), _
                    fields(1))
            Catch
                Throw New InvalidCastException(value)
            End Try
        Else
            Return MyBase.ConvertFrom(context, culture, _
                value)
        End If
    End Function

    Public Overloads Overrides Function ConvertTo(ByVal _
        context As _
        System.ComponentModel.ITypeDescriptorContext, ByVal _
        culture As System.Globalization.CultureInfo, ByVal _
        value As Object, ByVal destinationType As _
        System.Type) As Object
        If (destinationType.Equals(GetType(String))) Then
            Return value.ToString()
        Else
            Return MyBase.ConvertTo(context, culture, _
                value, destinationType)
        End If
    End Function

    Public Overloads Overrides Function _
        GetPropertiesSupported(ByVal context As _
        ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overloads Overrides Function GetProperties(ByVal _
        context As ITypeDescriptorContext, ByVal value As _
        Object, ByVal Attribute() As Attribute) As _
        PropertyDescriptorCollection
        Return TypeDescriptor.GetProperties(value)
    End Function
End Class

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

K výše uvedené třídě Person mám ještě prosbu

neřešil-li někdo, jak pracovat s výchozími

hodnotami. DefaltValue či DefaulValueAttribute

lze uvést přímo u property, mohou to však být

jenom konstanty,ale v tomto případě potřebuji

hodnoty nastavit při či po vytvoření třídy, potom

se změněné hodnoty zobrazí v propertygridu tučně,

nezměněné normálně. Lze attributy nastavovat vně

třídy, např. ReadOnly, DefaultValue či Browsable?

Nebo ve třídě nějak uchovávat OldValue, ale která

funkce zajištuje porovnání hodnot, jsou-li změněny

či nikoliv? Tip na nějaký pěkný příklad pro vlastní

třídu s osobou, bydliště, telefon, foto či tak něco?

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

U všech vlastností ve třídě je definován [ReadOnly] attribute,

potom pomocí SetReadOnlyProperty obsažené ve třídě mohu vně

nastavovat zda-li je vlastnost pro čtení, funguje...

Public Sub SetReadOnlyProperty(ByVal propertyName As String, ByVal readOnlyValue As Boolean)
        Dim descriptor As PropertyDescriptor = TypeDescriptor.GetProperties(Me.GetType)(propertyName)
        Dim attrib As ReadOnlyAttribute = CType(descriptor.Attributes(GetType(ReadOnlyAttribute)), ReadOnlyAttribute)
        Dim isReadOnly As FieldInfo = attrib.GetType.GetField("isReadOnly", (BindingFlags.NonPublic Or BindingFlags.Instance))
        isReadOnly.SetValue(attrib, readOnlyValue)
    End Sub

Pokouším se o podobné s [DefaultValue] ...

Avšak FieldInfo pro DefaultValue nelze získat, místo něj

pouze 'value', funguje, ale je postup níže správný?

Public Sub SetDefaultValueProperty(ByVal propertyName As String, ByVal [DefaultValue] As Object)
        Dim descriptor As System.ComponentModel.PropertyDescriptor = TypeDescriptor.GetProperties([GetType]())(propertyName)
        Dim attribute As DefaultValueAttribute = DirectCast(descriptor.Attributes(GetType(DefaultValueAttribute)), DefaultValueAttribute)
        Dim fieldToChange As System.Reflection.FieldInfo = attribute.[GetType]().GetField("value", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
        fieldToChange.SetValue(attribute, [DefaultValue])
    End Sub

Pokus nastavit výchozí hodnotu pomocí ShoulSerializePopertyName

se mi nedaří zprovoznit, nezkoušel někdo? Jak to má fungovat?

Přimlouvám se za seriál o property gridu, přidá se někdo?

nahlásit spamnahlásit spam 0 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