Cilj ovog teksta je da pokaže kako se postojeće ASP.NET serverske kontrole mogu relativno lako dograditi tako da im se poveća funkcionalnost. Kao primer sam uzeo GridView koji u osnovnoj postavi nema multiselect ali uz malo dorade postaje vrlo sličan gridovima koje srećemo u windows programiranju. Ideja je da možemo da izaberemo više redova u GridView tako što ćemo prilikom izbora držati taster CTRL.
Realizacija je sledeća: kad god kliknemo na neki red u GridView kontroli izvrši se registracija tog klika i nakon postback-a se čitaju indeksi kliknutih redova na osnovu kojih vraćamo redove u kontroli koji su izabrani.
Prvi korak je da kreiramo novu klasu koja će predstavljati DataGrid sa multiselect opcijom. Ona će biti izvedena iz System.Web.UI.WebControls.GridView klase i čime obezbeđujemo nasleđivanje svih osobina i metoda ove klase na koje smo navikli.
public class MultiSelectGridView : System.Web.UI.WebControls.GridView
Zatim je potrebno da na svaki red koji generiše osnovna GridView klasa “zalepimo” onclick javascript događaj (event handler). To radimo tako što promenimo OnRowDataBound metodu iz osnovne klase.
1: protected override void OnRowDataBound(GridViewRowEventArgs e)2: {3: base.OnRowDataBound(e);4:5: if (e.Row.DataItem != null)6: {7: e.Row.Attributes.Add("OnClick", "msel(event)");8:9: _id = this.PageIndex + "." + e.Row.RowIndex.ToString();10: e.Row.Attributes.Add("index", _id);11: }12: }
Glavna stvar se nalazi u liniji 7, gde na Row element dodajemo atribut OnClick koji će izvršavati msel(event) javascript funkciju na svaki klik. Javascript funkcija msel registruje gde se izvršio click događaj i upisuje indeks kliknutog elementa u skriveno (hidden) polje čiju vrednost ćemo kasnije, u postback-u, da parsiramo. Ovu funkciju ćemo da kreiramo i registrujemo kasnije.Sledeća stvar se nalazi na linijama 9 i 10. Naime, tu kreiramo indeks elementa koji je kliknut i vezujemo ga za sam element. Njegova konstrukcija je vrlo jednostavna, “_id = broj stranice + tačka + indeks trenutnog reda”. Dobijeni indeks se upisuje kao dodatni atribut u element koji predstavlja red u GridView-u.Da bi na klijentskoj strani znali koji red je izabran kreiramo Javascript funkciju “msel“ koju ćemo kasije da registrujemo na strani (podvučeni delovi code-a se automatski generišu u runtime-u).
Pre nego što prokomentarišem javascript code, da kažem par reči o html code-u koji generiše standardni GridView. GridView je u stvari obična tabela tj <table><tr><td>... konstrukcija. <tr> tag predstavlja red u našoj kontroli (Row) i na njega se “lepi” OnClick event. Sam event se zapravo okida na <td> elementu ali se propagira do prvog roditeljskog (parent) elementa koji ima handler tj definisan onclick a to je <tr> element. I evo javascript-a koji se generiše.Da prokomentarišemo javascript.
1:<script language="javascript">2: function msel(e, o)3: {
kreiramo referencu na skriveni (hidden) html element koji u sebi sadrži informacije koji redovi su selektovani
4: var selected = document.getElementById(o);
Zatim kreiramo referencu prema Event-u koji je inicirao izvršenje funkcije. Ova referenca nam treba da bi saznali koji je objekat inicirao Event i da li je pri kliku bio pritisnut taster CTRL. Linija 6 daje neposredni objekat koji je inicirao event, u ovom slučaju <td> tj ćeliju koja se nalazi unutar <tr> elementa. Na liniji 7 hvatamo sam <tr> element koji nosi informaciju o tome koji je indeks kliknutog elementa.
5: e = e ? e : ((window.event) ? event : null);6: var obj = e.target ? e.target : ((e.srcElement) ? e.srcElement : null);7: obj = obj.parentElement ? obj.parentElement : obj.parentNode;8: var objParent = obj.parentElement ? obj.parentElement : obj.parentNode;
Na linijama 9 i 10 kreiramo objekte String tipa koji redom nose podatke o izabranim redovima i o trenutno kliknutom objektu tj njegovom indeksu.
9: var sel = new String(selected.value);10: var id = new String(obj.getAttribute("index"));11: var cssclass;12:
Linija 13 ispituje da li je prilikom klika bio pritisnut i taster CTRL. Ukoliko jeste na liniji 14 proveravamo da li je red već izabran. Ukoliko jeste, ukloni ga iz liste izabranih i promeni css klasu za tekuću liniju. U suprotnom ubaci ga na listu izabranih i promeni css klasu.
13: if (e.ctrlKey) {14: if (sel.indexOf("-" + id + "-") > -1) {15: selected.value = sel.replace("-" + id + "-", "");16: obj.className = "CssClassRow";17: }18: else {19: selected.value = sel + "-" + id + "-"; 20: obj.className = "CssClassRowSelected";21: } 22: }
Ukoliko CTRL nije pritisnut (linija 23) lista izabranih indeksa svodi se na trenutno izabran a css klase se menjaju tako da su svi objekti neselektovani.
23: else { 24: if (sel.indexOf("-" + id + "-") > -1) { 25: cssclass = "CssClassRow"; selected.value = ""; 26: } 27: else { 28v cssclass = "CssClassRowSelected"; 29: selected.value = "-" + id + "-"; 30: } 31: var trs = objParent.getElementsByTagName("tr");32: for(i = 0; i < trs.length; i++) 33: if (trs[i].getAttribute("index"))34: trs[i].className = "CssClassRow";obj.className = cssclass;35: } 36: }
Napomena: podvučeni delovi se generišu
Funkcija disableSelection samo ne dozvoljava da se na kliknutim redovima izvrši selekcija teksta. Za detalje pogledajte http://www.dynamicdrive.com/dynamicindex9/noselect.htm.
37: function disableSelection(target) { 38: if (typeof target.onselectstart!="undefined") 39: target.onselectstart=function(){return false;}; 40: else if (typeof target.style.MozUserSelect!="undefined") 41: target.style.MozUserSelect="none"; 42: else 43: target.onmousedown=function(){return false;}; 44: target.style.cursor = "default"; 45: } 46:</script>
Ok, sledeća metoda koju menjamo u odnosu na originalnu GridView klasu je OnRowCreated.
1:protected override void OnRowCreated(GridViewRowEventArgs e)2:{3: base.OnRowCreated(e);4:5: _id = this.PageIndex + "." + e.Row.RowIndex.ToString();6:7: if (selected != null && selected.IndexOf("-" + _id + "-") > -1)8: e.Row.CssClass = CssClassRowSelected;9: else10: e.Row.CssClass = CssClassRow;11:}
Opet kreiramo indeks, linija 5, i ako je trenutni red u listi selektovanih onda mu menjamo css klasu.
I na kraju menjamo CreateChildcontrols metodu. Zapravo samo je proširujemo. Cilj je da između svakog postback-a očuvamo stanje selektovanih redova.
1:protected override void CreateChildControls()2:{
Naravno pustimo da se kreiraju sve potrebne kontrole koje se kreiraju za GridView (Linija 3)
3: base.CreateChildControls();4:5: string[] selectedArray;6:7: if (!string.IsNullOrEmpty(selected))8: {
Izdvojimo indekse redova selektovanih na client strani (linija 9.) .
9: selectedArray = selected.Split('-');10:
Kreiramo listu int vrednosti koja će sadržati indekse izabranih redova.
11: SelectedIndexs = new List<int>();
Kreiramo string niz koji će u sebi sadržati tekuću stranu i tekući index na strani.
12: string[] pageAndIndex;
Za svaki element u selectedArray a na osnovu stranice i indeksa preračunamo pravi indeks i ubacimo u SelectedIndexs.
13: foreach (string s in selectedArray)14: {15: if (s.Length > 0)16: {17: pageAndIndex = s.Split('.');18: SelectedIndexs.Add(int.Parse(pageAndIndex[0]) * this.PageSize + int.Parse(pageAndIndex[1]));19: }20: }21: }22:
Registrujemo skriveno html polje u koje upisujemo koji su izabrani redovi.
23: this.Page.ClientScript.RegisterHiddenField(selectedKey, selected);
Registrujemo blok sa javascript funkcijama opisanim gore.
24: this.Page.ClientScript.RegisterClientScriptBlock( ( (System.Web.UI.WebControls.GridView)this).GetType(), "MultiselectGridView_js", js);25:
I na kraju na GridView kontrolu dodamo još jednu literal kontrolu koja u sebi sadrži poziv funkcije disableSelection koja ne dozvoljava da se selektuje tekst na upravo kreiranoj kontroli.
26: Literal l = new Literal();27: l.Text = "<script language=\"javacript\" type=\"text/javascript\">disableSelection(document.getElementById(\"" + this.ClientID + "\"));</script>";28: this.Controls.Add(l);29:}
I to je to, kompletan code možete da skinete ovde.
Remember Me