DataGridView, Problém s Češtinou při Copy / Paste   otázka

VB.NET

Zkopíruje-li uživatel data z tabulky DataGridView, je po vložení např. do MS Excel nebo Word porušená diakritika. Přičemž při vložení do většiny jiných aplikací je diakritika v pořádku. Problém je v tom, že DataGridView ukládá do schránky data v několika formátech, mimo jiné v HTML. A aplikace Office si vyberou naneštěstí HTML. Nejen, že je pokřivené formátování, ale i špatná diakritika (Excel pravděpodobně očekává kódování UTF8, ale v tom to rozhodně DataGridView do schránky neuloží).

Nemáte na to prosím někdo něco ? Mě se podařilo vyGooglit jen tohle v céčku:

public override DataObject GetClipboardContent()

{

DataObject dataObject =

base.GetClipboardContent();

// HTML Format, Csv, Unicode Text, Text

DataObject newData = new

DataObject();

newData.SetData("Text", dataObject.GetData("Text"));

newData.SetData("UnicodeText",

dataObject.GetData("UnicodeText"));

return newData;

}

Přepsal jsem to (věřím, že správně) do vb:

    Public Overrides Function GetClipboardContent() As System.Windows.Forms.DataObject
        Dim dataObject As DataObject = MyBase.GetClipboardContent()
        'HTML Format, Csv, Unicode Text, Text
        Dim newData As DataObject = New DataObject
        newData.SetData("Text", dataObject.GetData("Text"))
        newData.SetData("UnicodeText", dataObject.GetData("UnicodeText"))
        Return newData
    End Function

Ale vždyť přeci ve Windows Forms Application je nadřazenou třídou System.Windows.Forms.Form. Jak tedy přepsat funkci, která patří do System.Windows.Forms.DataGridView ? Fakt jsem se hodně snažil pochopit OOP a jeho deklarace, ale ten správný zápis jsem ani po několika hodinách nedal. Navíc se mi při tom podařilo zbořit Designera (a to jsem mu ani nepsal do jeho kódu. Jen v mém Form1.vb přes Partial Class a Inherits, následované všemožnými pokusy o deklaraci přepisované funkce ... ).

A nebo doporučujete raději vytvořit vlastní obsluhu funkcionality Copy ? To stejně bude dobré asi udělat, aby byla komplexní. Jak nejlépe na to ? (stačí nakopnout) Nebo nějaké úplně jiné řešení ?

Díky Moc, Dalibor

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Zaprvé bych zkusil, jestli funguje obyčejné Clipboard.SetData tak jak je potřeba a případně toto použil místo té pochybné funkčnosti DataGridViewu.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

OK, díky, s tím by něměl být žádný problém. Napíšu to tedy ručně.

Ale přesto, pokusil by ses prosím vysvětlit, jak je to s tím přepisováním metod a funkcí ? Jak se přepisuje metoda nebo funkce, která není v nadřazené třídě, ale je jen součástí deklarovaného objektu ? (např. Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView) Jde to vůbec ? Podle toho, že to řešení (nahoře) jsem objevil na více místech, a že nikde nikdo nevysvětluje, jak to udělat, by to asi nějak jít mělo a dokonce to asi bude triviální. Ale pořádně jsem se v tom zamotal a budu Ti velmi vděčný, pokusíš-li se mě z toho vyvést. Díky Moc, Dalibor.

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

Zaprvé mi netykejte a za druhé takové věci jsou naprosto základní věci v OOP, které zde nehodlám vysvětlovat. V 7 z 10 případů metody přepisují ti, kteří nevědí, že existují události se stejným účelem a nic není nutné přepisovat.

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

Tak to se Vám velmi omlouvám, asi mě podvědomě svedl k tykání ten obrázek, či nějaké jiné téma. Nicméně, prosím, kdyby náhodou někdo měl náladu vyvést zoufalce z temného lesa, budu velmi vděčný. Fakt jsem toho nastudoval poměrně dost, ale asi je to tak triviální, že tohle nikdo nikde neřeší. Nechci přepisovat metody jak na běžícím páse, ale prostě chci prolomit to zoufalství, že jsem na to nepřišel.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Jak se přepisuje metoda nebo funkce, která není v nadřazené třídě, ale je jen součástí deklarovaného objektu

Pokud není metoda v nadřazené třídě, potom se nedá přepsat (override), ale pouze přetížit (overload). Přepsaná metoda je metoda se stejnou signaturou a názvem, ale jinou funkčností, přetížená metoda je metoda se stejným názvem, jinou signaturou a stejnou funkčností. Potom existuje také stínění metod (shadowing), což je velmi podobné přepisování. Do toho všeho je potřeba započítat jak se to všechno chová uložené v daném typu. Na první pohled jednoduchá problematika je při bližším pohledu velmi komplexní.

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

Děkuji Vám Velice. Až na to stínění metod jsem se tehdy dostal do podobné fáze vědění. Lze tedy tvrdit, že to nahoře v tom C# je nesmysl ? Výrazem pro Céčkové "override" je podle mých zjištění ve vb "Overrides". *** Vím, že původní neřízené C mohlo mít více nadřazených tříd. To by se ale nemělo týkat tohoto problému, protože, používá-li DataGridView, musí jít přeci o řízené C, kde již je to stejné, jako ve vb. Nebo se mýlím ?

*** S tím, že přetížení - overload - se za výše uvedeným účelem logicky použít nedá. (Přesto jsem to zkusil - a fungovalo dle očekávání - tedy na COPY - vnitřní funkcionalitu DataGridView - nemělo vliv)

Tady jsou ještě příklady odkazů na tu v úvodu uvedenou radu:

http://programujte.com/forum/vlakno/1221...

http://konference.vyvojar.cz/post.aspx?i...

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

Pane, plácáte nesmysly a já nemám náladu luštit, co bylo vaším textem míněno.

Nemáte žádný důvod přepisovat metody základní třídy, když můžete použít její události se stejnou funkčností. Toť vše.

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

Díky, již jsem Vás zdržel až až. Jasně, už to mám napsané růčo. Nicméně, nemyslím si, že jsou to úplné nesmysly. Také ty návody ve výše uvedených odkazech vypadaly poměrně zasvěceně, jeden z rádců dokonce zmínil, že psát vlastní obsluhu není to pravé. Proto jsem na tom tenkrát uvízl. Jsou to ale mrtvá témata, tak jsem si dovolil zeptat se zde. Třeba k tomu někdo ještě něco řekne.

V podstatě jde jen o to, jestli ten návod z těch odkazů (a nahoře v prvním příspěvku) je nesmysl a nebo jestli se to nakonec nějak udělat dá.

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

Výše uvedené odkazy nesmysl nejsou, nicméně je to násilné přeražení funkčnosti DataGridViewu. Jestliže se text vkládá špatně pouze do aplikací Office, potom je chyba v nich. Zkuste místo prostého vložení ze schránky použít příkaz Vložit jinak... To by mělo nabídnout i jiné možnosti než to, co se vybere jako výchozí.

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

Ano, "Vložit jinak..." samozřejmě funguje. Já bych to tak i dělal, nicméně, nuťte k tomu uživatele...

Říkáte "násilné přeražení funkčnosti". Jak by se to ale tedy udělalo, když ta funkce není v nadřazené třídě ? Prostě jsem na té problematice nechal noc a irituje mě, že jsem to nedal, přičemž způsob zápisu nikdo nikde neřeší, takže lze předjímat, že je to všeobecně známý postup.

Ale v tom clipboardu je při použití vnitřní funkcionality DataGridView to HTML polde mého názoru špatně. Některé znaky jsou v UTF8, některé ne. Zkoušel jsem si to v programu vyjíždět binárně, také, provedete-li paste do hex. editoru, je to vidět. Dále, programy MS Office provádějí paste HTML z jiných zdrojů než z DataGridViewu korektně. Takže podle mého názoru spíše asi bude chyba v tom DataGridViewu.

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

Buď přerazíte funkčnost v originální třídě a zároveň se tím zbavíte potenciální rozšířené funkčnosti pro ostatní programy a Vložit jinak..., nebo použijte mnou navrhované Clipboard.SetText a zachováte funkčnost DataGridViewu, která se může později potenciálně využít. S tím, že je v DataGridViewu spousta nedomyšlených věcí a možná i chyb souhlasím. Nahoďte to na MSDN a Microsoft označí vlákno za uzavřené s tím, že se na to vysere ještě ten den (vlastní zkušenost)...

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

Jasně, to vše chápu. Jde mi o to, jak (jakým postupem/zápisem) obecně "přerazím funkčnost v originální třídě", když ta funkce, kterou potřebuji změnit, není v nadřazené třídě. Děkuji za Vaši trpělivost.

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

No nic, děkuji všem, kdo se s tou problematikou přepisování zabývali a nebo budou zabývat a třeba nám k tomu ještě něco řeknou. Vzhledem k tomu, že i na msdn jsem zaregistroval zmíňku o možnosti přepsání nějaké metody DataGridWiewu, přičemž z toho nedělali žádnou vědu, asi to fakt bude běžné. Trochu tuším, že se asi bude muset upravit kód designeru. Možná by šlo kód předělat tak, aby nadřazenou třídou byl DataGridView. A nebo vytvořit novou třídu, jejíž nadřazenou třídou bude DataGridView a místo instance DataGridView (kterou normálně vytváří designer) vytvořit instanci této naší nové třídy. Už to ale metodou pokus omyl zkoušet nebudu, jedna noc stačila a designer je fakt prevít, nenechá si (ani na zkoušku/pokusně) skoro na nic šáhnout.

Dám sem tedy zatím jen řešení, které podle mého názoru velmi často bude vyhovovat a leckomu může pomoci. Stačí-li Vám obsloužit jednoduché CTRL+C, není nutné data vyzobávat ze selectu ručně, lze použít původní GetClipboardContent(), který jinak funguje poměrně pěkně, i na porůznu "rozházený" select.

    Private Sub DataGridView1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown
        'DataGridView1.GetClipboardContent() naplní do oldData:  HTML Format, Csv, UnicodeText, Text
        If e.KeyCode = 67 And e.Control Then
            Dim oldData As DataObject = DataGridView1.GetClipboardContent()
            Dim newData As DataObject = New DataObject
            If oldData IsNot Nothing Then
                newData.SetData("Text", oldData.GetData("Text"))
                newData.SetData("UnicodeText", oldData.GetData("UnicodeText"))
                Clipboard.SetDataObject(newData)
            End If
            e.Handled = True
        End If
    End Sub

Pro úplné vyloučení natažení dat s nekorektní češtinou je dobré ještě toto. Jiné řešení mě nenapadá, snad jedině na nižší úrovni obsluhy klávesnice, pomocí třídy keyboard. Tohle ale funguje a vzhledem k poměrně atypickému portfoliu formátů dat, kterými GetClipboardContent() naplňuje Clipboard, myslím, že data ve schránce z ostatních programů nejsou ohrožena. Interval Timer1 může být nastaven na 1000, nebo i více.

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        'V případě, že při CTRL+C zároveň probíhá editace buňky, interní DataGridView1.GetClipboardContent() naplní do Clipboardu:  HTML Format, Csv, UnicodeText, Text
        If Clipboard.ContainsData("HTML Format") And Clipboard.ContainsData("Csv") And Clipboard.ContainsData("UnicodeText") And Clipboard.ContainsData("Text") Then
            Dim oldData As DataObject = Clipboard.GetDataObject
            Dim newData As DataObject = New DataObject
            If oldData IsNot Nothing Then
                newData.SetData("Text", oldData.GetData("Text"))
                newData.SetData("UnicodeText", oldData.GetData("UnicodeText"))
                Clipboard.SetDataObject(newData)
            End If
        End If
    End Sub

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