Fókusz áthelyezése egy WPF DataGridben

Nem rég szembejött a probléma, hogy egy sokablakos, bonyolult WPF-app működése során néha kézzel – vagyis kóddal – kellene a fókuszt egy DataGrid egy sorára helyezni. A DataGrid.Focus() és a SelectedIndex beállításának kombója nem járható út, ilyenkor maga a Grid kapja meg a fókuszt, nem lehet rögtön lépkedni benne a le/fel nyilakkal.

Mit tehet ilyenkor az ember? Kiválasztja az adott sort a Rows tulajdonságból, és meghívja azon a Focust. Igen ám, de nem. Nincs Row/Rows tulajdonság, amiből kiválaszthatnánk a sorokat, illetve nincs GetRow metódus. Itt kezdené visszasírni az ember a DataGridViewt. 🙂

(Amúgy nem. Épp valamelyik nap kellett vele dolgoznom, és így 2-3 év WPF-ezés után már érzi az ember, hogy a DataGrid barátibb. Bár ez ízlés dolga.)

Akkor mit lehet tenni?

Nos, a DataGridnek, mint minden ItemsControlnak van egy Items tulajdonsága. Ezen keresztül elérhetjük az elemeket, amelyeket meg kell jelenítenie a gridnek. A probéma csak az, hogy ezek tényleg a megjelenítendő elemek. Az adatok a grid mögött, nem pedig a vizuális fában megjelenő sorok/cellák. Magyarán ez egy objectekből álló lista, tehát esélyünk sincs Focust hívni rajtuk, és kasztolni is max. az adattípusra tudjuk, amivel megint nem vagyunk beljebb.

Nem húzom tovább a dolgot (nem lenne mókás, ha végigvinnélek titeket azon a fél órás hajhulláson, amíg eljutottam a megoldásig 🙂 ), inkább prezentálom a végeredményt.

public static class DataGridExtender
{
    public static bool SetFocusOnDataGridRow(this DataGrid dg,
        int rownum = 0, bool setSelectedIndex = true)
    {
        if (rownum >= 0 && rownum < dg.Items.Count)
        {
            DataGridRow dgrow = (DataGridRow)dg.ItemContainerGenerator
                .ContainerFromItem(dg.Items[rownum]);
            if (setSelectedIndex) dg.SelectedIndex = rownum;
            return dgrow.Focus();
        }
        return false;
    }
}

Na, nézzük, mit látunk…

Ahogy látható, a C# 3.0 extension method (bővítőfüggvény) rendszerét használjuk, hogy a DataGrid osztálynak adjunk egy plusz metódust. A rownum paraméterrel várjuk, hogy mely sort akarják kiválasztani, a setSelectedIndex pedig azért “kell”, mert a fókuszáthelyezés és a grid kiválasztott elemének beállítása két külön dolog – ez a metódus képes lesz külön kezelni ezeket. A paraméterlistában kihasználom a C# 4.0-ás optional/named parameter fejlesztését, így a metódus gyakorlatilag paraméterek átadása nélkül is hívható lesz.

Ezek után jön a varázslat. A DataGrid ItemContainerGeneratorjának pontosan az a feladata, hogy egy adott adatelemhez (amit a fentebb ismertetett módon ki tudunk szedni a gridből) adjon nekünk egy olyan objektumot, ami a vizuális fában reprezentálja majd ezt az elemet. Vagyis eme objektum segítségével tudjuk áthidalni a szakadékot a megjelenítendő adat és a konkrét vizuális reprezentáció között.

A következő sor gondolom, világos: ha a programozó kérte, a selectedindexet is beállítjuk a sorra.

Ezután jön az, hogy akkor ki is jelöljük a sort, vagyis rárakjuk a fókuszt. Látható, hogy ez sem nehéz.

Ha kipróbáljátok, látni fogjátok, hogy azért nem tökéletes a leányzó fekvése. A sort kijelöli, a fókuszt is rárakja, de nem lehet rögtön mozogni a nyilakkal, mert a DataGridben cellánként megy az ugrálás – és most még nincs kijelölt cella.

A WPF-nek van egy nagyon szép bonyolult fókuszkezelő alrendszere, ami hajlamos igen randomisztikusan működni, de itt speciel pont jó lesz nekünk. Ha lecseréljük a “fókuszátrakó” sort a következőre, máris kijelöli az első cellánkat a fókusz rárakásánál:


return dgrow.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

Ennyi. Máris azonnal lépkedhető a gridünk. Remélem, sikerül megspórolnom némi kollektív hajhullást. 🙂

A WorkItemek nem oldják meg magukat, úgyhogy most (megintcsak) vissza kódolni.

ui.: bocs a kódszöveg mérete miatt, még harcolok a wordpress-szel, hogy ne legyen satu.

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
Reklámok

~ Szerző: Fülöp Dávid - 2011. április 15..

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

 
%d blogger ezt kedveli: