DataGrid常见关注问题解决方案
2004-10-28 15:33
549 查看
DataGrid常见关注问题解决方案
hbzxf(阿好)Introduction
TheDataGridWebservercontrolisapowerfultoolfordisplayinginformationfromadatasource.Itiseasytouse;youcandisplayeditabledatainaprofessional-lookinggridbysettingonlyafewproperties.Atthesametime,thegridhasasophisticatedobjectmodelthatprovidesyouwithgreatflexibilityinhowyoudisplaythedata.Thispaperaddressessomeofthequestionsaboutcustomizinggriddisplaythatarecommonlyaskedinnewsgroups,onWebsites,andinotherdeveloperforums.Thetechniquesdescribedherearesometimesquitesimpleandatothertimessomewhatinvolved.Ineachcase,however,theyaddressaquestionofhowtogobeyondthebasicfunctionalityoftheDataGridcontrol.
Thispaperassumesthatyouarealreadyfamiliarwiththecontrol—howtoaddittoaformandconfigureittodisplaydata.Youshouldalsounderstandhowtoputarowinthegridintoeditmodeandotherbasictasks.(Fordetails,see
WindowsFormsversusWebFormsDataGridControl
TheWebFormsDataGridcontrolisnotthesameastheWindowsFormsequivalent.Itisacommon(andnotunreasonable)assumptionthattheyarethesamecontrol,oratleasthaveidenticalfunctionality.However,theentireprogrammingparadigmforWebFormsisquitedifferentfromthatforWindowsForms.Forexample,WebFormspagesperformaroundtriptotheserverforanyprocessing;theymustmanagestate;theyfeatureaverydifferentdata-bindingmodel;andsoon.Becauseofthesedifferences,therearealsosignificantdifferencesintheirrespectivecontrols,includingtheDataGridcontrol.Asageneralrule,theWebFormsDataGridcontrolincludeslessbuilt-infunctionality.AfewexamplesofdifferencesintheWebFormsDataGridcontrolare:
Itdoesnotinherentlysupportmaster-detaildatastructures.
AswithotherWebservercontrols,itdoesnotsupporttwo-waydatabinding.Ifyouwanttoupdatedata,youmustwritecodetodothisyourself.
Youcanonlyeditonerowatatime.
Itdoesnotinherentlysupportsorting,althoughitraiseseventsyoucanhandleinordertosortthegridcontents.
Ontheotherhand:
YoucanbindtheWebFormsDataGridtoanyobjectthatsupportsthe
TheWebFormsDataGridcontrolsupportspaging.
ItiseasytocustomizetheappearanceandlayoutoftheWebFormsDataGridcontrolascomparedtotheWindowsFormsone.(Detailsareprovidedlaterinthispaper.)
ControllingColumnWidth,Height,andAlignment
Bydefault,theDataGridcontrolsizesrowsandcolumnstofittheoverallheightandwidththatyouhaveassignedtothegrid.Withintheoverallgridwidth,itsizescolumnsaccordingtothewidthofthecolumnheadingtext.Alldataisdisplayedleft-justifiedbydefault.Tocontrolcolumncharacteristics,youshouldturnoffautocolumngenerationbysettingtheAutoGenerateColumnspropertytofalse.Infact,youshouldsetthispropertytotrueonlyforshort-termuses,suchasquickproof-of-conceptpagesordemonstrations.Forproductionapplications,youshouldaddcolumnsexplicitly.Theindividualcolumnscanbeboundcolumnsortemplatecolumns.
Tosetthecolumnwidth,youcreateastyleelementforthatcolumnandthensettheelement'sWidthpropertytostandardunits(say,pixels).ThefollowingexampleshowsyouwhattheHTMLsyntaxlookslikeforanItemStyleelementwithitsWidthpropertyset.
<asp:BoundColumnDataField="title"SortExpression="title" HeaderText="Title"> [code]<ItemStyleWidth="100px"></ItemStyle>[/b]
</asp:BoundColumn>[/code]
Alternatively,youcandothesamethingbysettingtheItemStylepropertydirectlyintheelement,asinthefollowingexample:
<asp:BoundColumn[code]ItemStyle-Width="100px"[/b]DataField="title"
SortExpression="title"HeaderText="Title">
</asp:BoundColumn>[/code]
Youcansetalignmentusingthestyleelement,settingitto"Right,""Left,"andothervaluesdefinedintheHorizontalAlignenumeration.(InVisualStudio,alignmentisavailableforindividualcolumnsintheFormattabofthegrid'sPropertybuilder.)Thefollowingisanexample:
<asp:BoundColumnDataField="title"SortExpression="title" HeaderText="Title"> [code]<ItemStyleWidth="100px"HorizontalAlign="Right"></ItemStyle>[/b]
</asp:BoundColumn>[/code]
Youcanalsosetacolumn'sheightusingthestyleelement(ortheItemStyle-Heightproperty).Youwillprobablyfindthislessflexiblethansettingthewidth,sincesettingtheheightforonecolumnsetsitforallofthem.
Youcansetthewidthincodeatruntimeaswell.OneplacetodosoisinanItemCreatedeventhandler.Thefollowingexamplesetsthewidthofthefirsttwocolumnsto100and50pixels,respectively:
'VisualBasic PrivateSubDataGrid1_ItemCreated(ByValsenderAsObject,_ ByValeAsSystem.Web.UI.WebControls.DataGridItemEventArgs)_ HandlesDataGrid1.ItemCreated e.Item.Cells(0).Width=NewUnit(100) e.Item.Cells(1).Width=NewUnit(50) EndSub //C# privatevoidDataGrid1_ItemCreated(objectsender, System.Web.UI.WebControls.DataGridItemEventArgse) { e.Item.Cells[0].Width=newUnit(100); e.Item.Cells[1].Width=newUnit(50); }
Ofcourse,thereislittlesenseinsettingafixedwidthincodethatyoucouldsetatdesigntime.Youwouldnormallydothisonlyifyouwantedtosetthewidthbasedonarun-timevalue.Youcansetthewidthofacellorcontrolinunits(typicallypixels),butitisnotstraightforwardtotranslatethelengthofdata—whichissimplyacharactercount—intopixels.Butthedataisavailableforyoutoexaminewhenyouarecreatingtheitem.
CustomizingColumnLayoutinDisplayandEditMode
Bydefault,thegriddisplaysdatainpre-sizedcolumns.Whenyouputarowintoeditmode,thecontroldisplaystextboxesforalleditabledata,regardlessofwhatdatatypethedatais.Ifyouwanttocustomizethecontentofacolumn,makethecolumnatemplatecolumn.TemplatecolumnsworklikeitemtemplatesintheDataListorRepeatercontrol,exceptthatyouaredefiningthelayoutofacolumnratherthanarow.
Whenyoudefineatemplatecolumn,youcanspecifythefollowingtemplatetypes:
TheItemTemplateallowsyoutocustomizethenormaldisplayofthedata.
TheEditItemTemplateallowsyoutospecifywhatshowsupinthecolumnwhenarowisputintoeditmode.Thisishowyoucanspecifyacontrolotherthanthedefaulttextboxforediting.
AHeaderTemplateandFooterTemplateallowyoutocustomizetheheaderandfooter,respectively.(Thefooterisonlydisplayedifthegrid'sShowFooterpropertyistrue.)
ThefollowingexampleshowstheHTMLsyntaxforatemplatecolumnthatdisplaysBooleandata.BoththeItemTemplateandEditItemTemplateuseacheckboxtodisplaythevalue.IntheItemTemplate,thecheckboxisdisabledsothatusersdonotthinktheycancheckit.IntheEditItemTemplate,thecheckboxisenabled.
<Columns> <asp:TemplateColumnHeaderText="Discontinued"> <ItemTemplate> <asp:Checkboxrunat="server"enabled=falsename="Checkbox2" ID="Checkbox2" Checked='<%#DataBinder.Eval(Container, "DataItem.Discontinued")%>'> </asp:Checkbox> </ItemTemplate> <EditItemTemplate> <asp:Checkbox runat="server"name="Checkbox2"ID="Checkbox2" Checked='<%#DataBinder.Eval(Container, "DataItem.Discontinued")%>'> </asp:Checkbox> </EditItemTemplate> </asp:TemplateColumn> </Columns>
Note[/b]IfyouuseaCheckBoxcontrolintheEditItemTemplate,beawarethatatruntime,thegridcellactuallycontainsseveralLiteralControlcontrols(forspacing)inadditiontothecheckboxitself.WheneveryouknowtheIDofthecontrolwhosevalueyouwant,usetheFindControlmethodtocreateareferencetoit,ratherthanusingspecificindexesintotheCellsandControlscollections:
'VisualBasic DimcbAsCheckBox cb=CType(e.Item.FindControl("CheckBox2"),CheckBox) //C# CheckBoxcb; cb=(CheckBox)e.Item.FindControl("CheckBox2");
InVisualStudio,youcanusethegrid'sPropertybuildertocreatethetemplatecolumnandusethetemplateeditortospecifythelayout.IntheColumnstabofthePropertieswindowpageforthegrid,selectthecolumnandatthebottom,clickConvertthiscolumnintoaTemplateColumn.ClosethePropertieswindow,right-clickthegrid,andchooseEditTemplate.YoucanthendragcontrolsfromtheToolboxintothetemplateandaddstatictext.
FormattingDates,Currency,andOtherData
InformationinaDataGridcontrolisultimatelydisplayedinanHTMLtableintheWebFormspage.Tocontrolhowdataisdisplayed,therefore,youcanspecify.NETstringformattingforcolumnvalues.Youcannotspecifyformattingforcolumnsgeneratedwhenthegrid'sAutoGenerateColumnspropertyissettotrue,onlyforboundortemplatecolumns.Toformat,setthecolumn'sDataFormatStringpropertytoastring-formattingexpressionsuitableforthedatatypeofthedatayouareformatting.Aslightlyconfusingaspectofformatstringsisthatthesamespecifier—forexample,"D"—canbeappliedtodifferentdatatypes(integers,dates)withdifferentresults.
Note[/b]InVisualStudio,youcanspecifyaformattingexpressionintheColumnstabofthecontrol'sPropertybuilder.
Someexampleformattingstringsarelistedinthefollowingtable.Formoreinformation,seethetopics
Formatexpression | Appliedtothisdatatype | Description |
---|---|---|
Price:{0:C} Note[/b]The{0}isazero,nottheletterO. | numeric/decimal | Displaystheliteral"Price:"followedbynumbersincurrencyformat.ThecurrencyformatdependsontheculturesettingspecifiedviathecultureattributeonthePagedirectiveorintheWeb.configfile. |
{0:D4} | integer(Cannotbeusedwithdecimalnumbers.) | Integersaredisplayedinazero-paddedfieldfourcharacterswide. |
{0:N2}% | numeric | Displaysthenumberwith2-decimalplaceprecisionfollowedbytheliteral"%". |
{0:000.0} | numeric/decimal | Numbersroundedtoonedecimalplace.Numberslessthanthreedigitsarezeropadded. |
{0:D} | date/datetime | Longdateformat("Thursday,August06,1996").DateformatdependsontheculturesetttingofthepageortheWeb.configfile. |
{0:d} | date/datetime | Shortdateformat("12/31/99"). |
{0:yy-MM-dd} | date/datetime | Dateinnumericyear-month-dayformat(96-08-06). |
ShowingandHidingColumnsDynamically
Onewaytohavecolumnsappeardynamicallyistocreatethematdesigntime,andthentohideorshowthemasneeded.Youcandothisbysettingacolumn'sVisibleproperty.Thefollowingexampleshowshowtotogglethevisibilityofthesecondcolumn(index1)ofthegrid:'VisualBasic DataGrid1.Columns(1).Visible=Not(DataGrid1.Columns(1).Visible) //C# DataGrid1.Columns[1].Visible=!(DataGrid1.Columns[1].Visible);
AddingColumnsDynamically
Youcanhideandshowcolumnsifyouknowinadvancewhatcolumnsyouneed.Sometimes,however,youdonotknowthatuntilruntime.Inthatcase,youcancreatecolumnsdynamicallyandaddthemtothegrid.Todoso,youcreateaninstanceofoneofthecolumnclassessupportedbythegrid—BoundColumn,EditCommandColumn,ButtonColumn,orHyperlinkColumn.(Youcanaddtemplatecolumnstothegrid,butitisslightlymorecomplex.Fordetails,see
Thefollowingexampleshowshowtoaddtwoboundcolumnstoagrid.
'VisualBasic PrivateSubButton1_Click(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesButton1.Click 'Setdata-bindingpropertiesofthegrid DataGrid1.AutoGenerateColumns=False DataGrid1.DataSource=Me.dsBooks1 DataGrid1.DataMember="Books" DataGrid1.DataKeyField="bookid" 'Addtwocolumns Dimdgc_idAsNewBoundColumn() dgc_id.DataField="bookid" dgc_id.HeaderText="ID" dgc_id.ItemStyle.Width=NewUnit(80) DataGrid1.Columns.Add(dgc_id) Dimdgc_titleAsNewBoundColumn() dgc_title.DataField="title" dgc_title.HeaderText="Title" DataGrid1.Columns.Add(dgc_title) Me.SqlDataAdapter1.Fill(Me.dsBooks1) DataGrid1.DataBind() EndSub //C# privatevoidButton1_Click(objectsender,System.EventArgse) { DataGrid1.AutoGenerateColumns=false; DataGrid1.DataSource=this.dsBooks1; DataGrid1.DataMember="Books"; DataGrid1.DataKeyField="bookid"; //Addtwocolumns BoundColumndgc_id=newBoundColumn(); dgc_id.DataField="bookid"; dgc_id.HeaderText="ID"; dgc_id.ItemStyle.Width=newUnit(80); DataGrid1.Columns.Add(dgc_id); BoundColumndgc_title=newBoundColumn(); dgc_title.DataField="title"; dgc_title.HeaderText="Title"; DataGrid1.Columns.Add(dgc_title); this.sqlDataAdapter1.Fill(this.dsBooks1); DataGrid1.DataBind(); }
Anytimethatyouaddcontrolstoapagedynamically,youhavetheproblemofpersistence.Dynamically-addedcontrols(orinthiscase,columns)arenotautomaticallyaddedtothepage'sviewstate,soyouareobligedtoaddlogictothepagetomakesurethecolumnsareavailablewitheachroundtrip.
Anexcellentwaytodothisistooverridethepage'sLoadViewStatemethod,whichgivesyouanearlyopportunitytoreestablishcolumnsintheDataGridcontrol.BecausetheLoadViewStatemethodiscalledbeforethePage_Loadeventisraised,re-addingcolumnsintheLoadViewStatemethodassuresthattheyareavailablefornormalmanipulationbythetimeanyeventcoderuns.
Thefollowingexampleshowshowyouwouldexpandthepreviousexampletorestorethecolumnseachtimethepagerunsagain.Asbefore,theButton1_Clickhandleraddstwocolumnstothegrid.(Inthisexample,theeventhandlercallsaseparateroutinecalledAddColumnstodoso.)Inaddition,thepagecontainsasimpleBooleanpropertycalledDynamicColumnsAddedindicatingwhetherthegridhashadcolumnsadded;thepropertypersistsitsvalueinviewstate.TheLoadViewStatemethodfirstcallsthebaseclass'sLoadViewStatemethod,whichextractsviewstateinformationandconfigurescontrolswithit.Ifcolumnswerepreviouslyaddedtothegrid(aspertheDynamicColumnsAddedproperty),themethodthenre-addsthem.
'VisualBasic PrivatePropertyDynamicColumnAdded()AsBoolean Get IfViewState("ColumnAdded")IsNothingThen ReturnFalse Else ReturnTrue EndIf EndGet Set(ByValValueAsBoolean) ViewState("ColumnAdded")=Value EndSet EndProperty ProtectedOverridesSubLoadViewState(ByValsavedStateAsObject) MyBase.LoadViewState(savedState) IfMe.DynamicColumnAddedThen Me.AddColums() EndIf EndSub PrivateSubButton1_Click(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesButton1.Click 'Checkpropertytobesurecolumnsarenotaddedmorethanonce IfMe.DynamicColumnAddedThen Return Else Me.AddColums() EndIf EndSub ProtectedSubAddColums() 'Addtwocolumns Dimdgc_idAsNewBoundColumn() dgc_id.DataField="instock" dgc_id.HeaderText="InStock?" dgc_id.ItemStyle.Width=NewUnit(80) DataGrid1.Columns.Add(dgc_id) Dimdgc_titleAsNewBoundColumn() dgc_title.DataField="title" dgc_title.HeaderText="Title" DataGrid1.Columns.Add(dgc_title) Me.DataGrid1.DataBind() Me.DynamicColumnAdded=True EndSub //C# privateboolDynamicColumnAdded{ get { objectb=ViewState["DynamicColumnAdded"]; return(b==null)?false:true; } set { ViewState["DynamicColumnAdded"]=value; } } protectedoverridevoidLoadViewState(objectsavedState) { base.LoadViewState(savedState); if(DynamicColumnAdded) { this.AddColumns(); } } privatevoidButton1_Click(objectsender,System.EventArgse) { if(this.DynamicColumnAdded!=true) { this.AddColumns(); } } privatevoidAddColumns() { BoundColumndgc_id=newBoundColumn(); dgc_id.DataField="bookid"; dgc_id.HeaderText="ID"; dgc_id.ItemStyle.Width=newUnit(80); DataGrid1.Columns.Add(dgc_id); BoundColumndgc_title=newBoundColumn(); dgc_title.DataField="title"; dgc_title.HeaderText="Title"; DataGrid1.Columns.Add(dgc_title); this.sqlDataAdapter1.Fill(this.dsBooks1); DataGrid1.DataBind(); this.DynamicColumnAdded=true; }
AddingNewRecordstoaDataSourceUsingtheDataGridControl
TheDataGridcontrolallowsuserstoviewandeditrecords,butdoesnotinherentlyincludethefacilitytoaddnewones.However,youcanaddthisfunctionalityinvariousways,allofwhichinvolvethefollowing:Addinganew,blankrecordtothedatasourceofthegrid(inthedatasetordatabase).Ifnecessary,youwillneedtoassignanIDfortherecordandputplaceholdervaluesintoitforanycolumnsthatcannotbenull.
RebindingtheDataGridcontroltothesource.
Puttingthegridintoeditmodeforthenewrecord.Youneedtobeabletodeterminewhereinthegridthenewrecordappears.
UpdatingtherecordnormallywhentheuserclicksUpdate,therebywritingthenewrecordtothesourcewithuser-providedvalues.
Thefollowingexampleshowstheprocessforaddingthenewrecord,bindingthegrid,andputtingitintoeditmode.Inthisexample,thedatasourceisadataset(DsBooks1ordsBooks1)containingatablecalled"Books."
'VisualBasic PrivateSubbtnAddRow_Click(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesbtnAddRow.Click DimdrAsDataRow=Me.DsBooks1.Books.NewRow dr("title")="(New)" dr("instock")=True Me.DsBooks1.Books.Rows.InsertAt(dr,0) Session("DsBooks")=DsBooks1 DataGrid1.EditItemIndex=0 DataGrid1.DataBind() EndSub //C# privatevoidbtnAddRow_Click(objectsender,System.EventArgse) { DataRowdr=this.dsBooks1.Books.NewRow(); dr["title"]="(New)"; dr["instock"]=true; this.dsBooks1.Books.Rows.InsertAt(dr,0); Session["DsBooks"]=dsBooks1; DataGrid1.EditItemIndex=0; DataGrid1.DataBind(); }
Somethingstonotice:
ThiscoderunswhenauserclicksanAddbuttonsomewhereinthepage.
ThenewrowiscreatedusingtheNewRowmethod.ItistheninsertedintothedatasettableusingtheInsertAtmethod,whichallowsyoutoplaceitataspecific,predefinedlocation—inthiscase,asthefirstrecordinthetable(thatis,thefirstrecordintheRowscollection).Alternatively,youcouldaddittotheendofthetable,usingtherowcountasthevalue.Theimportantthingisthatyouknowexactlywheretherowisinthetable.
Becauseyouknowthattherecordisinthefirstpositionofthetable,youcansetthegrid'sEditItemIndexvaluetozerotoputthenewrowintoeditmode.(Ifyoucreatedtherowelsewhereinthetable,youwouldsetEditItemIndextothatlocationinstead.)
Becauseyouhaveanewrecordinthedataset(butnotyetinthedatabase),youhavetokeepacopyofthedatasetbetweenroundtrips—youdonotwanttorefillitfromthedatabaseandlosethenewrecord.Here,thecodestoresitinSessionstate.YouneedtoreloadthedatasetfromSessionstatewhenthepageloads.ThefollowingexampleshowswhatyourPage_Loadhandlermightlooklike:
'VisualBasic PrivateSubPage_Load(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesMyBase.Load IfMe.IsPostBackThen DsBooks1=CType(Session("DsBooks"),dsBooks) Else Me.SqlDataAdapter1.Fill(Me.DsBooks1) Session("DsBooks")=DsBooks1 DataGrid1.DataBind() EndIf EndSub //C# privatevoidPage_Load(objectsender,System.EventArgse) { if(this.IsPostBack) { dsBooks1=(dsBooks)Session["DsBooks"]; } else { this.sqlDataAdapter1.Fill(this.dsBooks1); Session["DsBooks"]=dsBooks1; this.DataGrid1.DataBind(); } }
Forinformationaboutmaintainingstate,see
Youcanupdatetherecordnormally.Foranexample,see
'VisualBasic PrivateSubDataGrid1_UpdateCommand(ByValsourceAsObject,_ ByValeAsSystem.Web.UI.WebControls.DataGridCommandEventArgs)_ HandlesDataGrid1.UpdateCommand DimdrAsDataset.BooksRow 'Getareferencetorowzero(wheretherowwasinserted) dr=Me.DsBooks1.Books(0) DimtbAsTextBox=CType(e.Item.Cells(2).Controls(0),TextBox) dr.title=tb.Text DimcbAsCheckBox=CType(e.Item.Cells(3).Controls(1),CheckBox) dr.instock=cb.Checked Me.SqlDataAdapter1.Update(Me.DsBooks1) DataGrid1.EditItemIndex=-1 'Refreshthedatasetfromthedatabase DsBooks1.Clear() Me.SqlDataAdapter1.Fill(Me.DsBooks1) 'SavetherefresheddatasetinSessionstateagin Session("DsBooks")=DsBooks1 DataGrid1.DataBind() EndSub //C# privatevoidDataGrid1_UpdateCommand(objectsource, System.Web.UI.WebControls.DataGridCommandEventArgse) { dsBooks.BooksRowdr; //Getareferencetorowzero(wheretherowwasinserted) dr=this.dsBooks1.Books[0]; TextBoxtb1=(TextBox)e.Item.Cells[2].Controls[0]; dr.title=tb1.Text; CheckBoxcb=(CheckBox)e.Item.Cells[3].Controls[1]; dr.instock=cb.Checked; this.sqlDataAdapter1.Update(this.dsBooks1); DataGrid1.EditItemIndex=-1; //Refreshthedatasetfromthedatabase dsBooks1.Clear(); this.sqlDataAdapter1.Fill(this.dsBooks1); //SavetherefresheddatasetinSessionstateagin Session["DsBooks"]=dsBooks1; DataGrid1.DataBind(); }
DisplayingaDrop-DownListinEditMode
Acommonrequestistopresentuserswithadrop-downlistwhenarowisineditmode.Forexample,thegridmightshowalistofbooks,includingeachbook'sgenre.Whenuserseditabookrecord,theymightwanttoassignadifferentgenre;ideally,theycanselectfromadrop-downlistthatshowspossiblegenrevaluessuchas"fiction,""biography,"or"reference."Displayingadrop-downlistrequiresatemplatecolumninthegrid.Typically,theItemTemplatecontainsacontrolsuchasadata-boundLabelcontroltoshowthecurrentvalueofafieldintherecord.Youthenaddadrop-downlisttotheEditItemTemplate.InVisualStudio,youcanaddatemplatecolumninthePropertybuilderforthegrid,andthenusestandardtemplateeditingtoremovethedefaultTextBoxcontrolfromtheEditItemTemplateanddragaDropDownListcontrolintoitinstead.Alternatively,youcanaddthetemplatecolumninHTMLview.
Afteryouhavecreatedthetemplatecolumnwiththedrop-downlistinit,therearetwotasks.Thefirstistopopulatethelist.Thesecondistopreselecttheappropriateiteminthelist—forexample,ifabook'sgenreissetto"fiction,"whenthedrop-downlistdisplays,youoftenwant"fiction"tobepreselected.(Preselectinganitemmightnotbeanissueinallscenarios.)
Therearemanywaystopopulatethedrop-downlist.Thefollowingexamplesshowyouthreepossibilities:usingstaticitems;usingrecordsfromadataset;orbyusingadatareadertoreadinformationdirectlyfromadatabase.
StaticItems
Todisplaystaticitemsinthedrop-downlist,youdonotdatabindthecontrol.Instead,yousimplydefineitemsinthecontrol'sItemscollection.InVisualStudio,youcaninvoketheItemscollectioneditorfromtheItemspropertyinthePropertieswindow.Alternatively,youcanadditemsinHTMLview.Thefollowingshowsacompletecolumndefinitionforatemplatecolumnthatdisplaysthegenreindisplaymode,andastaticlistofgenretypesineditmode.TheItemTemplatecontainsaLabelcontrolwhoseTextpropertyisboundtothe"genre"fieldofthecurrentrecord.ThedeclarationsforthestaticitemsintheEditItemTemplatearehighlighted.
<asp:TemplateColumnHeaderText="genre"> <ItemTemplate> <asp:Labelid=Label4runat="server" Text='<%#DataBinder.Eval(Container,"DataItem.genre")%>'> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:DropDownListid="DropDownList2"runat="server"Width="172px"> [code]<asp:ListItemValue="fiction">fiction</asp:ListItem>[/b]
<asp:ListItemValue="biography">biography</asp:ListItem>[/b]
<asp:ListItemValue="reference">reference</asp:ListItem>[/b]
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateColumn>[/code]
Dataset
Ifthedatayouwanttodisplayinthedrop-downlistisinadataset,youcanuseordinarydatabinding.Thefollowingshowsthedeclarativesyntax.TheDropDownListcontrolisboundtotheGenretableinadatasetcalledDsBooks1.Thedata-bindingsettingsarehighlighted.<asp:TemplateColumnHeaderText="genre(dataset)"> <ItemTemplate> <asp:Labelid=Label3runat="server" Text='<%#DataBinder.Eval(Container,"DataItem.genre")%>'> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:DropDownListid=DropDownList4runat="server" DataSource="<%#DsBooks1%>"DataMember="Genre" DataTextField="genre"DataValueField="genre"Width="160px"> </asp:DropDownList> </EditItemTemplate> </asp:TemplateColumn>
DataReader
Youcanalsopopulatethedrop-downlistdirectlyfromadatabase.Thismethodismoreinvolved,butitcanbemoreefficient,sinceyoudonotactuallyreadthedatafromthedatabasetillthemomentyouneedit.ArelativelyeasywaytodothisistotakeadvantageofWebFormsdata-bindingexpressions.AlthoughitismostcommontocalltheDataBinder.Evalmethodinadata-bindingexpression,youcaninfactcallanypublicmemberavailabletothepage.Thisexampleshowsyouhowtocreateafunctionthatcreates,fills,andreturnsaDataTableobjectthatthedrop-downlistcanbindto.
Forthisscenario,youwillneedtobeabletoexecuteadatacommandthatgetstherecordsyouwant.Forexample,youmightdefineadatacommandwhoseCommandTextpropertyis
Select*fromGenres.Tosimplifytheexample,itwillbeassumedthatyouhaveaconnectionobjectandadatacommandobjectalreadyonthepage.
Startbycreatingapublicfunctioninthepagethatcreatesadatatableobjectanddefinesthecolumnsyouneedinit.Thenopentheconnection,executethedatacommandtoreturnadatareader,andloopthroughthereader,copyingthedatatothetable.Finally,returnthetableasthefunction'sreturnvalue.
Thefollowingexampleshowshowyoucandothis.Inthiscase,thereisonlyonecolumninthereturnedtable("genre").Whenyoupopulateadrop-downlist,youusuallyneedonlyonecolumn,ortwocolumnsifyouwanttosetthedrop-downlist'stextandvaluestodifferentcolumns.
'VisualBasic PublicFunctionGetGenreTable()AsDataTable DimdtGenreAsDataTable=NewDataTable() IfApplication("GenreTable")IsNothingThen DimdrAsDataRow DimdcAsNewDataColumn("genre") dtGenre.Columns.Add(dc) Me.SqlConnection1.Open() DimdreaderAsSqlClient.SqlDataReader=_ Me.SqlCommand1.ExecuteReader() Whiledreader.Read() dr=dtGenre.NewRow() dr(0)=dreader(0) dtGenre.Rows.Add(dr) EndWhile Me.SqlConnection1.Close() Else dtGenre=CType(Application("GenreTable"),DataTable) EndIf ReturndtGenre EndFunction //C# publicDataTableGetGenreTable() { DataTabledtGenre=newDataTable(); if(Application["GenreTable"]==null) { DataRowdr; DataColumndc=newDataColumn("genre"); dtGenre.Columns.Add(dc); this.sqlConnection1.Open(); System.Data.SqlClient.SqlDataReaderdreader= this.sqlCommand1.ExecuteReader(); while(dreader.Read()) { dr=dtGenre.NewRow(); dr[0]=dreader[0]; dtGenre.Rows.Add(dr); } this.sqlConnection1.Close(); } else { dtGenre=(DataTable)Application["GenreTable"]; } returndtGenre; }
NoticethatthefunctioncachesthetableitcreatesintoApplicationstate.Sincethetableisactingasastaticlookuptable,youdonotneedtore-readiteverytimeadifferentrowisputintoeditmode.Moreover,becausethesametablecanbeusedbymultipleusers,youcancacheitintheglobalApplicationstateratherthaninuser-specificSessionstate.
Thefollowingshowsthedeclarationforthetemplatecolumn.Youwillseethatthisisverysimilartothesyntaxusedforbindingtoadatasettable;theonlyrealdifferenceisthattheDataSourcebindingcallsyourfunction.Aslightdisadvantageofthistechniqueisthatyoudonotgetmuchdesign-typeassistancefromVisualStudio.Becauseyouaredefiningthetabletobindtoincode,VisualStudiocannotofferyouanychoicesfortheDataMember,DataTextField,andDataValueFieldpropertysettings.Itisuptoyoutobesurethatyousetthesepropertiestothenamesofthemembersyoucreateincode.
<asp:TemplateColumnHeaderText="genre(database)"> <ItemTemplate> <asp:Labelid=Label1runat="server" Text='<%#DataBinder.Eval(Container,"DataItem.genre")%>'> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:DropDownListid=DropDownList1runat="server" [code]DataSource="<%#GetGenreTable()%>"[/b]
DataMember="Genre"
DataTextField="genre"
DataValueField="genre"
Width="120px">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateColumn>[/code]
PreselectinganItemintheDrop-DownList
Youoftenwanttosettheselectediteminthedrop-downlisttomatchaspecificvalue,usuallythevaluedisplayedinthecellindisplaymode.YoucandothisbysettingtheSelectedIndexpropertyofthedrop-downlisttotheindexofthevaluetodisplay.ThefollowingexampleshowsareliablewaytodothisinahandlerfortheDataGriditem'sItemDataBoundevent.Thisisthecorrecteventtouse,becauseitguaranteesthatthedrop-downlisthasalreadybeenpopulated,nomatterwhatdatasourcethedrop-downlistisusing.
Thetrickisinknowingwhatvaluetosetthedrop-downlistto.Typically,thevalueisalreadyavailabletoyoueitherinthecurrentitem(beingdisplayed)orintheDataItempropertyofthecurrentitem,whichreturnsaDataRowViewobjectcontainingthecurrentrecord.Onceyouhavethevalue,youcanusetheDropDownListcontrol'sFindByTextorFindByValuemethodtolocatethecorrectiteminthelist;youcanthenusetheitem'sIndexOfpropertytoreturntheindex.
'VisualBasic PrivateSubDataGrid1_ItemDataBound(ByValsenderAsObject,_ ByValeAsSystem.Web.UI.WebControls.DataGridItemEventArgs)_ HandlesDataGrid1.ItemDataBound Ife.Item.ItemType=ListItemType.EditItemThen DimdrvAsDataRowView=CType(e.Item.DataItem,DataRowView) DimcurrentgenreAsString=CType(drv("genre"),String) DimddlAsDropDownList ddl=CType(e.Item.FindControl("DropDownList1"),DropDownList) ddl.SelectedIndex=ddl.Items.IndexOf(ddl.Items.FindByText(currentgenre)) EndIf EndSub //C# privatevoidDataGrid1_ItemDataBound(objectsender, System.Web.UI.WebControls.DataGridItemEventArgse) { if(e.Item.ItemType==ListItemType.EditItem){ DataRowViewdrv=(DataRowView)e.Item.DataItem; Stringcurrentgenre=drv["genre"].ToString(); DropDownListddl= (DropDownList)e.Item.FindControl("DropDownList1"); ddl.SelectedIndex= ddl.Items.IndexOf(ddl.Items.FindByText(currentgenre)); } }
SelectingMultipleItemsUsingaCheckBox(HotmailModel)
InapplicationssuchasMicrosoftHotmail®,userscan"select"rowsbycheckingaboxandthenperforminganoperationonalltheselectedrows—forexample,deletethemorcopythem.Toaddfunctionalitylikethis,addatemplatecolumntothegridandputacheckboxintothecolumn.Whenthepageruns,userswillbeabletochecktheitemstheywanttoworkwith.
Toactuallyperformtheuseraction,youcanwalkthegrid'sItemscollection,lookingintotheappropriatecolumn(cell)toseeifthecheckboxischecked.Thefollowingexampleshowshowyoucandeleterowsinadatasetcorrespondingtotheitemsthatauserhaschecked.Thedataset,calleddsBooks1,isassumedtocontainatablecalledBooks.
'VisualBasic PrivateSubbtnDelete_Click(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesbtnDelete.Click 'Walkthegridlookingforselectedrows DimiAsInteger=0 DimcbAsCheckBox DimdgiAsDataGridItem DimbookidAsInteger DimdrAsdsBooks.BooksRow ForEachdgiInDataGrid1.Items cb=CType(dgi.Cells(0).Controls(1),CheckBox) Ifcb.CheckedThen 'Determinethekeyoftheselectedrecord... bookid=CType(DataGrid1.DataKeys(i),Integer) '...getapointertothecorrespondingdatasetrecord... dr=Me.DsBooks1.Books.FindBybookid(bookid) '...anddeleteit. dr.Delete() EndIf i+=1 Next Me.SqlDataAdapter1.Update(DsBooks1) Me.SqlDataAdapter1.Fill(DsBooks1) DataGrid1.DataBind() EndSub //C# privatevoidbtnDelete_Click(objectsender,System.EventArgse) { inti=0; CheckBoxcb; intbookid; dsBooks.BooksRowdr; foreach(DataGridItemdgiinthis.DataGrid1.Items) { cb=(CheckBox)dgi.Cells[0].Controls[1]; if(cb.Checked) { //Determinethekeyoftheselectedrecord... bookid=(int)DataGrid1.DataKeys[i]; //...getapointertothecorrespondingdatasetrecord... dr=this.dsBooks1.Books.FindBybookid(bookid); //...anddeleteit. dr.Delete(); } i++; } this.sqlDataAdapter1.Update(this.dsBooks1); this.sqlDataAdapter1.Fill(this.dsBooks1); DataGrid1.DataBind(); }
Somepointstonote:
Youcandeterminewhetherthecheckboxischeckedbyusingthestandardapproachforgettingacontrolvaluefromatemplatecolumn—gettinganobjectfromtheControlscollectionofthecellandcastingitappropriately.IfyouaregettingaCheckboxcontrol,rememberthatitisusuallythesecondcontrol(index1)becausealiteralcontrolprecedesit(evenifitisblank).
Ifyouaredeleting,youmustdosobykeyandnotbyoffsetinthedataset.TheindexofanitemintheDataGridcontrolmightnotmatchtheindexofthesamerecordinthetable.Evenifitdoesatfirst,afterthefirstrecordisdeleteditwillnot.Here,thecodegetstherecordkeyoutofthegrid'sDataKeycollection.ItthenusestheFindBy<key>methodinthedatasettabletolocatetherecordtodelete.
Aftertherecordshavebeendeletedfromthedataset(technically,theyareonlymarkedfordeletion),youdeletethemfromthedatabasebycallingthedataadapter'sUpdatemethod.Thecodethenrefreshesthedatasetfromthedatabaseandre-bindsthegrid.
EditingMultipleRowsAtOnce
ThestandardwaytoeditrowsintheDataGridcontrol—byaddingan"Edit,Update,Cancel"buttontothegrid'scolumns—onlyallowsuserstoeditonerowatatime.Ifuserswanttoeditmultiplerows,theymustclicktheEditbutton,maketheirchanges,andthenclicktheUpdatebuttonforeachrow.Insomecases,ausefulalternativeistoconfigurethegridsothatitisineditmodebydefault.Inthisscenario,thegridalwaysdisplayseditabledataintextboxesorothercontrols;usersdonotexplicitlyhavetoputthegridintoeditmode.Typically,usersmakewhateverchangestheywantandthenclickabutton(notabuttoninthegrid)tosubmitallchangesatonce.Thepagemightlooksomethinglikethefollowing:
Figure1
Youcanusethisstyleofeditinggridwithanydatamodel,whetheryouareworkingagainstadatasetordirectlyagainstthedatasourceusingdatacommands.
Toconfigurethegridformultiple-rowedit,addthecolumnsasyounormallywouldandconvertalleditablecolumnstotemplatecolumns.IntheColumnstabofthegrid'sPropertyBuilder,selectthecolumnandatthebottomofthewindow,chooseConvertthiscolumnintoaTemplatecolumn.Toeditthetemplates,right-clickthegridandchooseEditTemplate.
AddtheeditcontrolstotheItemTemplate.NotethatyouarenotaddingthemtotheEditItemTemplate,asyounormallywould,becausetherowswillnotbedisplayedineditmode.Thatis,theItemTemplatewillcontaineditablecontrols.
Setupdatabindingforthegridnormally.Youwillneedtobindeacheditablecontrolindividually.Atypicaldatabindingexpressionwilllooklikethis:
DataBinder.Eval(Container,"DataItem.title")
Loadingthegridisnodifferentthanusual.Updatingisslightlydifferent,however,becausewhenusersclicktheUpdatebutton,youneedtogothroughtheentiregrid,makingupdatesforalltherows.
Thefollowingexampleshowsonepossibility.Inthiscase,itisassumedthatyouareusingadatacommand(dcmdUpdateBooks)thatcontainsaparameterizedSQLUpdatestatement.Thecodewalksthroughthegrid,itembyitem,extractsvaluesfromtheeditablecontrols,andassignsthevaluestocommandparameters.Itthenexecutesthedatacommandonceforeachgriditem.
'VisualBasic PrivateSubbtnUpdate_Click(ByValsenderAsSystem.Object,_ ByValeAsSystem.EventArgs)HandlesbtnUpdate.Click DimiAsInteger DimdgiAsDataGridItem DimbookidAsInteger DimTextBoxTitleAsTextBox DimCheckBoxInStockAsCheckBox DimTextBoxPriceAsTextBox DimLabelBookIdasLabel Fori=0ToDataGrid1.Items.Count-1 dgi=DataGrid1.Items(i) LabelBookId=CType(dgi.Cells(0).Controls(1),Label) bookid=CType(LabelBookId.Text,Integer) TextBoxTitle=CType(dgi.FindControl("TextBoxTitle"),TextBox) CheckBoxInStock=_ CType(dgi.FindControl("CheckBoxInstock"),CheckBox) TextBoxPrice=CType(dgi.FindControl("TextBoxPrice"),TextBox) Me.dcmdUpdateBooks.Parameters("@bookid").Value=bookid Me.dcmdUpdateBooks.Parameters("@Title").Value=TextBoxTitle.Text Me.dcmdUpdateBooks.Parameters("@instock").Value=_ CheckBoxInStock.Checked Me.dcmdUpdateBooks.Parameters("@Price").Value=TextBoxPrice.Text Me.SqlConnection1.Open() Me.dcmdUpdateBooks.ExecuteNonQuery() Me.SqlConnection1.Close() Next EndSub //C# privatevoidbtnUpdate_Click(objectsender,System.EventArgse) { inti; DataGridItemdgi; intbookid; TextBoxTextBoxTitle; CheckBoxCheckBoxInStock; TextBoxTextBoxPrice; for(i=0;i<=DataGrid1.Items.Count-1;i++) { dgi=DataGrid1.Items[i]; LabelLabelBookId=(Label)dgi.Cells[0].Controls[1]; bookid=int.Parse(LabelBookId.Text); TextBoxTitle=(TextBox)dgi.FindControl("TextBoxTitle"); CheckBoxInStock=(CheckBox)dgi.FindControl("CheckBoxInStock"); TextBoxPrice=(TextBox)dgi.FindControl("TextBoxPrice"); this.dcmdUpdateBooks.Parameters["@bookid"].Value=bookid; this.dcmdUpdateBooks.Parameters["@Title"].Value=TextBoxTitle.Text; this.dcmdUpdateBooks.Parameters["@instock"].Value= CheckBoxInStock.Checked; this.dcmdUpdateBooks.Parameters["@Price"].Value= float.Parse(TextBoxPrice.Text); this.sqlConnection1.Open(); this.dcmdUpdateBooks.ExecuteNonQuery(); this.sqlConnection1.Close(); } }
CheckingforChangedItems
Onedisadvantageoftheupdatestrategyillustratedaboveisthatitcanbeinefficienttosendupdatestothedatasetordatabaseforeachgridrowiftherehavebeenonlyafewchanges.Ifyouareworkingwithadataset,youcanaddlogictocheckforchangesbetweenthecontrolsinthegridandthecorrespondingcolumnsindatasetrows.Ifyouarenotusingadataset—asintheexampleabove—youcannoteasilymakethiscomparison,sinceitwouldinvolvearoundtriptothedatabase.Astrategythatworksforbothtypesofdatasourcesistoestablishawaytodeterminewhetherrowsare"dirty"soyoucancheckthatbeforemakinganupdate.Thedefinitivewaytodeterminewhetherarowhasbeendirtiedistohandlethechangedeventforthecontrolsinarow.Forexample,ifyourgridrowcontainsaTextBoxcontrol,youcanrespondtothecontrol'sTextChangedevent.Similarly,forcheckboxes,youcanrespondtoaCheckedChangedevent.
Inthehandlerfortheseevents,youmaintainalistoftherowstobeupdated.Generally,thebeststrategyistotracktheprimarykeysoftheaffectedrows.Forexample,youcanmaintainanArrayListobjectthatcontainstheprimarykeysoftherowstoupdate.
Imaginethatyouwanttofollowthisstrategyfortheexampleabove.CreateaninstanceofanArrayListobjectasamemberofthepageclass:
'VisualBasic ProtectedbookidlistAsArrayList=NewArrayList() //C# protectedArrayListbookidlist=newArrayList();
ThencreateahandlertoaddthebookIDtotheArrayListobjectwheneveracontrolischanged.ThefollowingcodeshowsahandlerthatcanbeinvokedwhenaTextBoxcontrolraisesitsTextChangedeventorwhenaCheckBoxcontrolraisesitsCheckedChangedevent:
'VisualBasic ProtectedSubRowChanged(ByValsenderAsObject,_ ByValeAsSystem.EventArgs) DimdgiAsDataGridItem=_ CType(CType(sender,Control).NamingContainer,DataGridItem) DimbookidlabelAsLabel=CType(dgi.Cells(0).Controls(1),Label) DimbookidAsInteger=CType(bookidlabel.Text,Integer) IfNot(bookidlist.Contains(bookid))Then bookidlist.Add(bookid) EndIf EndSub //C# protectedvoidRowChanged(objectsender,System.EventArgse) { DataGridItemdgi=(DataGridItem)(((Control)sender).NamingContainer); Labelbookidlabel=(Label)dgi.Cells[0].Controls[1]; intbookid=int.Parse(bookidlabel.Text); if(!bookidlist.Contains(bookid)) { bookidlist.Add(bookid); } }
Note[/b]Themethodcannotbeprivate,oryouwillnotbeabletobindtoitlater.
Itishelpfultounderstandthatchangeeventsdonot,bydefault,postthepagebacktotheserver.Instead,theeventisraisedonlywhenthepageispostedsomeotherway(usuallyviaaClickevent).Duringpageprocessing,thepageanditscontrolsareinitialized,andthenallchangeeventsareraised.Onlywhenthechangeevent'shandlershavefinishedistheClickeventraisedforthecontrolthatcausedthepost.
OntotheRowChangedmethodillustratedabove.ThecodeneedstogetthebookIDoutofthecurrentitem.Theeventdoesnotpasstheitemtoyou(asitdoesformanyDataGridevents,forexample),soyouhavetoworkbackwards.Fromthe
senderargumentoftheevent,gettheNamingContainerproperty,whichwillbethegriditem.Fromthere,youcandrillbackdowntogetthevalueoftheLabelcontrolthatdisplaysthebookID.
YouneedtocheckthatthebookIDisnotalreadyinthearray.Eachcontrolintherowraisestheeventindividually,soiftherehasbeenachangeinmorethanonecontrol,youcouldpotentiallyendupaddingthebookIDtothearraymorethanonce.
Thechangeeventsforcontrolsarealwaysraisedandhandledbeforeclickevents.Therefore,youcanbuildthearraylistinthechangeeventandknowthatitwillbeavailablewhentheeventhandlerrunsforthebuttonclickthatpostedtheform(inthisexample,the
btnUpdate_Clickhandler).
Nowthatyouhavethearraylist,youcanmakeaminormodificationtothehandlerthatmanagestheupdate.Inthe
btnUpdate_Click,whenyouiteratethroughthedatagriditems,addatesttoseeifthecurrentbookIDisinthearraylist;ifso,maketheupdate.
'VisualBasic
PrivateSubbtnUpdate_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)HandlesbtnUpdate.Click
DimiAsInteger
DimdgiAsDataGridItem
'Restofdeclarationshere
Fori=0ToDataGrid1.Items.Count-1
dgi=DataGrid1.Items(i)
LabelBookId=CType(dgi.Cells(0).Controls(1),Label)
[code]Ifbookidlist.Contains(bookid)Then[/b]
TextBoxTitle=CType(dgi.FindControl("TextBoxTitle"),TextBox)
'Restofupdatecodehere
EndIf[/b]
Next
EndSub
//C#
privatevoidbtnUpdate_Click(objectsender,System.EventArgse)
{
inti;
DataGridItemdgi;
intbookid;
//Restofdeclarationshere
for(i=0;i<=DataGrid1.Items.Count-1;i++)
{
dgi=DataGrid1.Items[i];
TableCelltc=dgi.Cells[0];
strings=dgi.Cells[0].Text;
LabelLabelBookId=(Label)dgi.Cells[0].Controls[1];
bookid=int.Parse(LabelBookId.Text);
if(bookidlist.Contains(bookid))[/b]
{[/b]
//Updatecodehere
}[/b]
}
}[/code]
Onetaskisleft:bindingthehandlerstothecontrolevents.InVisualStudio,youcanonlydothisinHTMLview.Thecontrolsarenotexplicitlyinstantiatedinthecode-behindfile,sotheyarenotsupportedbythecodetools.Switchthe.aspxfiletoHTMLviewandinthedeclarativeelementsforeachofthecontrols,addthefollowinghighlightedsyntax:
<asp:TemplateColumnHeaderText="title"> <ItemTemplate> <asp:TextBox[code]OnTextChanged="RowChanged"[/b]
id=TextBoxTitlerunat="server"
Text='<%#DataBinder.Eval(Container,"DataItem.title")%>'>
</asp:TextBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumnHeaderText="instock">
<ItemTemplate>
<asp:CheckBoxid=cbInStock
OnCheckedChanged="RowChanged"[/b]
runat="server"
Checked='<%#DataBinder.Eval(Container,"DataItem.instock")%>'>
</asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>[/code]
BoththeTextBoxandCheckBoxcontrolscancallthesamemethodfromtheirrespectivechangemethods,becausethesignatureforbotheventhandlersisthesame.Thatwouldbetruealsoifyouhadalistboxordrop-downlistcontrol,whoseSelectedIndexChangedeventslikewisepassthesamearguments.
SelectingRowsbyClickingAnywhere
ThedefaultmodelforselectingrowsinthegridisforyoutoaddaSelectbutton(actually,aLinkButtoncontrol)whoseCommandNamepropertyissetto"Select."Whenthebuttonisclicked,theDataGridcontrolreceivestheSelectcommandandautomaticallydisplaystherowinselectedmode.NoteveryonelikeshavinganexplicitSelectbutton,andacommonquestionishowtoimplementthefeaturewhereuserscanclickanywhereinagridrowtoselectit.Thesolutionistoperformakindofsleight-of-handinthegrid.YouaddtheSelectLinkButtoncontrolasnormal.Userscanstilluseit,oryoucanhideit.Ineitherevent,youtheninjectsomeclientscriptintothepagethateffectivelyduplicatesthefunctionalityoftheSelectbuttonfortherowasawhole.
Theexamplebelowshowshow.Inthegrid'sItemDataBoundhandler,firstmakesurethatyouarenotintheheader,footer,orpager.ThengetareferencetotheSelectbutton,whichinthisinstanceisassumedtobethefirstcontrolinthefirstcell.Youthencallalittle-knownmethodcalledGetPostBackClientHyperlink.Thismethodreturnsthenameofthepostbackcallforthedesignatedcontrol.Inotherwords,ifyoupassinareferencetoaLinkButtoncontrol,itreturnsthenameoftheclientfunctioncallthatwillperformthepostback.
Finally,youassigntheclient-sidemethodtotheitemitself.Whenthegridrenders,itrendersasanHTMLtable.Byassigningthemethodtotheitem,itistheequivalentofaddingclient-sidecodetoeachrow(<TR>element)inthetable.Thegrid'sItemobjectdoesnotdirectlysupportawaytoassignclientcodetoit,butyoucandothatbyusingitsAttributescollection,whichpassesanythingyouassigntoitthroughtothebrowser.
Note[/b]Onesmalldisadvantageofthistechniqueisthatitaddssomewhattothestreamrenderedtothebrowser,anditaddsinformationforeachrowtoviewstate.
'VisualBasic
PrivateSubDataGrid1_ItemDataBound(ByValsenderAsObject,_
ByValeAsSystem.Web.UI.WebControls.DataGridItemEventArgs)_
HandlesDataGrid1.ItemDataBound
DimitemTypeAsListItemType=e.Item.ItemType
If((itemType=ListItemType.Pager)Or_
(itemType=ListItemType.Header)Or_
(itemType=ListItemType.Footer))Then
Return
Else
DimbuttonAsLinkButton=_
CType(e.Item.Cells(0).Controls(0),LinkButton)
e.Item.Attributes("onclick")=_
Page.GetPostBackClientHyperlink(button,"")
EndIf
EndSub
//C#
privatevoidDataGrid1_ItemDataBound(objectsender,
System.Web.UI.WebControls.DataGridItemEventArgse)
{
ListItemTypeitemType=e.Item.ItemType;
if((itemType==ListItemType.Pager)||
(itemType==ListItemType.Header)||
(itemType==ListItemType.Footer))
{
return;
}
LinkButtonbutton=(LinkButton)e.Item.Cells[0].Controls[0];
e.Item.Attributes["onclick"]=
Page.GetPostBackClientHyperlink(button,"");
}
出自MSDN:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchTopQuestionsAboutASPNETDataGridServerControl.asp
相关文章推荐
- DataGrid常见关注问题解决方案
- DataGrid常见关注问题解决方案
- DataGrid常见关注问题解决方案
- cpc(国际专利标准)离线客户端文档制作公式失真(字体变粗变黑)问题解决方案以及常见注意事项
- hbase+eclipse 常见问题解决方案
- 倾力总结40条常见的移动端Web页面问题解决方案
- datagrid因排序造成的添加删除问题解决方案
- ubuntu 16.04下搜狗输入法不能输入中文解决(linux下常见软件崩溃问题解决方案)
- Win Server2003常见问题及解决然方案
- SQL2000常见安装中问题解决方案
- datagrid因排序造成的添加删除问题解决方案
- Win Server2003常见问题及解决然方案
- CSS常见兼容问题解决方案(持续更新)
- SQL2000常见安装中问题解决方案
- 【转】40条常见的移动端Web页面问题解决方案
- 23 API-多线程(多线程概述,多线程实现方案,线程控制常见方法,线程安全问题及解决)
- 移动端开发常见问题解决方案汇总- Javascript技巧(一)
- 倾力总结40条常见的移动端Web页面问题解决方案
- XP常见问题解决方案
- Easy ui DataGrid 列文字多串行问题解决方案