您的位置:首页 > 其它

DataGrid常见关注问题解决方案

2004-10-28 15:33 549 查看

DataGrid常见关注问题解决方案

hbzxf(阿好)
http://www.hebcom.net

Introduction

TheDataGridWebservercontrolisapowerfultoolfordisplayinginformationfromadatasource.Itiseasytouse;youcandisplayeditabledatainaprofessional-lookinggridbysettingonlyafewproperties.Atthesametime,thegridhasasophisticatedobjectmodelthatprovidesyouwithgreatflexibilityinhowyoudisplaythedata.

Thispaperaddressessomeofthequestionsaboutcustomizinggriddisplaythatarecommonlyaskedinnewsgroups,onWebsites,andinotherdeveloperforums.Thetechniquesdescribedherearesometimesquitesimpleandatothertimessomewhatinvolved.Ineachcase,however,theyaddressaquestionofhowtogobeyondthebasicfunctionalityoftheDataGridcontrol.

Thispaperassumesthatyouarealreadyfamiliarwiththecontrol—howtoaddittoaformandconfigureittodisplaydata.Youshouldalsounderstandhowtoputarowinthegridintoeditmodeandotherbasictasks.(Fordetails,seeDataGridWebServerControl.)Finally,youwillfindithelpfultoknowhowtoworkwithtemplates—addingtemplatecolumnstothegridandlayoutoutcontrolsinsideatemplate.

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:

YoucanbindtheWebFormsDataGridtoanyobjectthatsupportstheIEnumerableinterface.
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,seethetopicsFormattingTypesandBoundColumn.DataFormatStringPropertyintheVisualStudiodocumentation.

FormatexpressionAppliedtothisdatatypeDescription
Price:{0:C}
Note[/b]The{0}isazero,nottheletterO.
numeric/decimalDisplaystheliteral"Price:"followedbynumbersincurrencyformat.ThecurrencyformatdependsontheculturesettingspecifiedviathecultureattributeonthePagedirectiveorintheWeb.configfile.
{0:D4}integer(Cannotbeusedwithdecimalnumbers.)Integersaredisplayedinazero-paddedfieldfourcharacterswide.
{0:N2}%numericDisplaysthenumberwith2-decimalplaceprecisionfollowedbytheliteral"%".
{0:000.0}numeric/decimalNumbersroundedtoonedecimalplace.Numberslessthanthreedigitsarezeropadded.
{0:D}date/datetimeLongdateformat("Thursday,August06,1996").DateformatdependsontheculturesetttingofthepageortheWeb.configfile.
{0:d}date/datetimeShortdateformat("12/31/99").
{0:yy-MM-dd}date/datetimeDateinnumericyear-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,seeCreatingWebServerControlTemplatesProgrammatically.)Setthecolumn'sproperties,andthenaddittothegrid'sColumnscollection.

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,seeWebFormsStateManagementintheVisualStudiodocumentation.

Youcanupdatetherecordnormally.Foranexample,seeWalkthrough:UsingaDataGridWebControltoReadandWriteDataintheVisualStudiodocumentation.Afterupdatingthedataset,updatethedatabase,thenrefreshthedataset.BesuretosavetherefresheddatasettoSessionstateagain.Hereisanexampleofanupdatehandler:
'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
sender
argumentoftheevent,gettheNamingContainerproperty,whichwillbethegriditem.Fromthere,youcandrillbackdowntogetthevalueoftheLabelcontrolthatdisplaysthebookID.

YouneedtocheckthatthebookIDisnotalreadyinthearray.Eachcontrolintherowraisestheeventindividually,soiftherehasbeenachangeinmorethanonecontrol,youcouldpotentiallyendupaddingthebookIDtothearraymorethanonce.

Thechangeeventsforcontrolsarealwaysraisedandhandledbeforeclickevents.Therefore,youcanbuildthearraylistinthechangeeventandknowthatitwillbeavailablewhentheeventhandlerrunsforthebuttonclickthatpostedtheform(inthisexample,the
btnUpdate_Click
handler).

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


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: