TypeConvertery

2. díl - TypeConvertery

Jan Novák       28.12.2008       VB.NET, Komponenty, WinForms, .NET       12201 zobrazení

V tomto díle si vysvětlíme, co jsou TypeConvertery a k čemu se používají. To si také ukážeme na příkladu.

TypeConverter je třída ve jmenném prostoru System.ComponentModel. Jak již název napovídá, slouží ke konverzi mezi dvěma datovými typy. V praxi se většinou jedná o konverzi mezi řetězcem a vlastním datovým typem. TypeConverter zajistí převod datového typu na řetězec (ten se pak zobrazí v PropertyGridu) a zpět. Tato funkcionalita je velmi důležitá pro to, aby nám PropertyGrid umožnil editovat neframeworkové typy stejně, jako frameworkové.

Praxe

Každý prvek, který dědí z Control, dědí i vlastnost Location. Její hodnota je datového typu Point. Point má vlastnosti X a Y. Pokud si na formulář umístíme nějaký takový prvek (e.g. Button) a přejdeme na vlastnost Location, uvidíme jí v Properties reprezentovanou řetězcem "X, Y". Location můžeme rozkliknout na X a Y a editovat každou složku zvlášť, ale také můžeme do Location napsat přímo řetězec se souřadnicemi. Pak nastupují TypeConvertery. PropertyGrid předá TypeConverteru řetězec a ten zkontroluje zda je ve správném formátu (pokud ne, vyhodí výjimku) a překonvertuje na Point. Výsledný Point vrátí a PropertyGrid jej nastaví objektu, který edituje.

Třídu TypeConverter rozšiřuje několik dalších typů konverterů v System.ComponentModel. Například:

  • ArrayConverter
  • ByteConverter
  • BooleanConverter
  • CollectionConverter
  • ... a mnoho dalších

Tyto konvertery jsou psané na míru pro určité datové typy. Nás ale bude zajímat hlavně třída ExpandableObjectConverter. Pokud náš TypeConverter bude dědit z této třídy, PropertyGrid k vlastnosti přidá PlusMinus, jež umožní její rozkliknutí na složky.

Aplikace

Vlastní konvertery se aplikují na datový typ, ne na vlastnost. Aplikují se pomocí atributu TypeConverter. My si teď vytvoříme třídu Song, která bude obsahovat některé základní informace o písni. Na ní si později ukážeme používání TypeConverterů.

Public Class Song

    Private _title As String = String.Empty
    Private _artist As String = String.Empty
    Private _album As String = String.Empty

    Public Property Title() As String
        Get
            Return _title
        End Get
        Set(ByVal value As String)
            _title = value
        End Set
    End Property

    ' ... a vlastnosti Artist a Album

End Class

Teď si do našeho projektu přidáme komponentu Person z minulého dílu. Pokud jste minulý díl nečetli, můžete si zdrojové kódy stáhnout zde:

Zdrojové kódy

Otevřme se třídu Person a přidejme jí vlastnost Song (já jí umístím do kategorie Oblíbené). Tato vlastnost je typu Song. Když si sestavíme projekt, uvidíme následující:

vlastnost Song nelze upravovat

Jak můžeme vidět, vlastnost Song (zde reprezentovaná jako 'Oblíbená skladba' pomocí DisplayName) je zašedlá a nemůžeme ji editovat. Jedná se totiž o vlastnost, která nabývá hodnoty vlastního datového typu (Song) a neexistuje pro ni TypeConverter, proto nám PropertyGrid nedokáže nabídnout její editaci.

Konverter

Napíšeme si tedy TypeConverter pro konverzi mezi řetězcem a Song. Konvence velí pojmenovávat konvertery podle datového typu, jež konvertují, pojmenujme tedy SongConverter. Konverter bude dědit z ExpandableObjectConverter a bude overridovat čtyři metody: CanConvertFrom, CanConvertTo, ConvertFrom a ConvertTo.

Public Class SongConverter
    Inherits ExpandableObjectConverter

    ' CanConvertFrom, CanConvertTo, ConvertFrom, ConvertTo

End Class

CanConvertFrom, CanConvertTo

CanConvertFrom je funkce, jež udává, zda umí konverter konvertovat z daného datového typu. Ta naše bude vypadat takto:

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

CanConvertTo udává, pokud umí konvertor konvertovat na daný typ. PropertyGrid bude zajímat, pokud umí konvertovat na String.

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

ConvertFrom, ConvertTo

ConvertFrom je funkce, která vrací výsledný objekt, který TypeConverter konvertuje. PropertyGrid bude potřebovat, aby konverter uměl konvertovat ze Stringu.

Public 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 str As String = DirectCast(value, String)
        Dim rex As String = "^([^-\(\)]+) - ([^-\(\)]+) \(([^-\(\)]+)\)$"
        ' Za RegEx děkuji panu Jechovi. Více o RegularExpressions na konci článku.
        If Regex.IsMatch(str, rex) Then
            With Regex.Match(str, rex)
                Return New Song(.Groups(1).Value, .Groups(2).Value, .Groups(3).Value)
            End With
        Else
            Throw New ArgumentException(str & " don't match '" & rex & "'")
            Return Nothing
        End If
    End If
    Return MyBase.ConvertFrom(context, culture, value)
End Function

ConvertTo převádí obráceně - z objektu na řetězec (v případě PropertyGrid):

Public 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 Is GetType(String) AndAlso value IsNot Nothing Then
        Dim sng As Song = DirectCast(value, Song)
        Return String.Format("{0} - {1} ({2})", sng.Artist, sng.Title, sng.Album)
    End If
    Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function

vlastnost je možno <em>rozkliknout</em> na složky

Jak vidíme, TypeConverter odvedl svou práci. Pokud změníme hodnotu vlastnosti Song na jiný řetězec ve správném formátu (Interpet - Náze Skladby (Název Alba)), aktualizují se i vnořené vlastnosti. Vlastnost je také možno rozkliknout (znaménko plus).

Jediný problém je, že pokud aktualizujeme nějakou subvlastnost, vlastnost Song se neaktualizuje okamžitě, ale až při editací jí samotné. Toto chování je možné snadno upravit. Stačí všem vlastnostem třídy Song přidat atribut RefreshProperties. Ten si jako parametr bere hodnotu enumerace System.ComponentModel.RefreshProperties. Jejími členy jsou None (výchozí chování), Repaint a All. Nám postačí Repaint. Ten PropertyGridu řekne, že se má překreslit. All by znamenalo, že se mají vlastnosti znovu zjistit a pak překreslit, ale to je v tomto případě zbytečné.

<RefreshProperties(RefreshProperties.Repaint)> _

Závěrem

Jak jsem slíbil v článku, řeknu také něco k RegularExpressions. Jedná se o pokročilou techniku práce s řetězci, zvlášťě pak vyhledávání a nahrazování určitých částí na základě daných pravidel. Více o RE n následující stránkách:

  1. regularnivyrazy.info (externí)
  2. regular-expressions.info (externí)
  3. regexlib.com (externí)

Doufám že se Vám článek líbil. Příště si ukážeme práci s UITypeEditory. O co se jedná napoví obrázek:

úprava vlastnosti Dock pomocí dropdowneditoru

Zdrojové kódy

 

hodnocení článku

1 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Všechny díly tohoto seriálu

3. UITypeEditory 09.02.2009
2. TypeConvertery 28.12.2008
1. Atributy jmenného prostoru System.ComponentModel 23.12.2008

 

 

 

Nový příspěvek

 

Regex

Nějak jsem nepochopil ten regex, tedy regulérní výrazy. Přimlouval bych se za to, zda by někdo nemohl napsat článek na toto téma. Bylo by to možné?

Jinak je tento velmii přínosný (možná více než Wikipedia) a já za něj jeho autorům moc děkuji.

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

Promiňte, chybička se vloudila do poslední věty. Opravuji: Jinak je tento web velmi přínosný ....

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

Diskuse: TypeConvertery

Na http://www.vbnet.cz/forum-tema--4834-uni... je univezální TypeConverter.

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.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • 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