I am creating a WEB report in Visual Studio 2010 in VB.net. The report needs to display a table (please see the attached image). I am thinking to use the GridView component which i think it's the most appropriate one to choose. In the database there are students' data and marks. I can't alter the database in any way and i have to use Visual Studio 2010 with VB.
What i need to do is to show 3 different pictures(for example) depend on the student's marks. I got the pictures file in PNGs but this can be flexible.For example, over 70 will be a Smile picture. over 60 will be the Normal face. and over 40 will be the picture with no smile. I bit difficult for me to explain but i hope u get my point.
So pls advice me how can i achieve this. I am quite a newbie to this pls put as detail as you can. if there is a choice between client and server side script, i prefer server side script. Data source can be flexible (sql, or linq or anything).
You should use RowDataBound to bind data to controls in your GridView.
Following is a complete sample with aspx and codebehind(says more than thousand words):
<style type="text/css">
.GridViewRowStyle
{
background-color: #A0CFEC;
color:Blue;
}
.GridViewAlternatingRowStyle
{
background-color:White;
color:#15317E;
}
.GridViewHeaderStyle
{
background-color:White;
color:#15317E;
}
</style>
<asp:GridView ID="GridStudents" AutoGenerateColumns="false" GridLines="None" runat="server">
<RowStyle CssClass="GridViewRowStyle" />
<AlternatingRowStyle CssClass="GridViewAlternatingRowStyle" />
<HeaderStyle CssClass="GridViewHeaderStyle" />
<Columns>
<asp:TemplateField HeaderText="Student">
<ItemTemplate>
<asp:label runat="server" ID="LblStudent" Text='<%# Bind("Student") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Mark">
<ItemTemplate>
<asp:label runat="server" ID="LblMark" Text='<%# Bind("Mark") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Image runat="server" ID="ImgSmiley" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Codebehind(with sample-data):
Private Sub GridStudents_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridStudents.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim row = DirectCast(e.Row.DataItem, DataRowView)
Dim ImgSmiley = DirectCast(e.Row.FindControl("ImgSmiley"), Image)
Select Case DirectCast(row("Mark"), Int32)
Case Is < 50
ImgSmiley.ImageUrl = "~/Images/Smiley_Grim.png"
ImgSmiley.ToolTip = "bad"
Case Is < 70
ImgSmiley.ImageUrl = "~/Images/Smiley_Def.png"
ImgSmiley.ToolTip = "ok"
Case Else
ImgSmiley.ImageUrl = "~/Images/Smiley_Laugh.png"
ImgSmiley.ToolTip = "fine"
End Select
End Select
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
BindData()
End If
End Sub
Private Sub BindData()
Dim tblStudent As New DataTable("Students")
Dim colStudent = New DataColumn("Student", GetType(String))
Dim colMark As New DataColumn("Mark", GetType(Int32))
tblStudent.Columns.Add(colStudent)
tblStudent.Columns.Add(colMark)
Dim newRow = tblStudent.NewRow
newRow("Student") = "Tom"
newRow("Mark") = 70
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Bob"
newRow("Mark") = 40
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Danny"
newRow("Mark") = 60
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Sussie"
newRow("Mark") = 40
tblStudent.Rows.Add(newRow)
GridStudents.DataSource = tblStudent
GridStudents.DataBind()
End Sub
Related
so I have a gridview which is displaying a db table I have.
I dont create the table manually obviously as this is what <%#Eval("text")%>' and Bind() do.
I created a unique table with my sql query to add two rows of sum in the bottom of the table, ( 2 last records), my question is:
is there a way in which I can access those rows to style them?
I think its not possible but still Im asking maybe Ill find out that theres a way.
thanks
Yes, the need to style a individual cell (auto generated columns, or bound columns), or even style the whole row.
Let's do all 3
First up, style a "cell" (these are in the cells collection, and autogenerated columns, and NON templated columns).
So, say this simple grid
<asp:GridView ID="GridView1" runat="server" Width="40%"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:Label ID="lblDescript" runat="server"
Text='<%# Eval("Description") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server"
Checked='<%# Eval("Active") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
(note how I included BOTH templated columns which have plain jane asp.net controls like label, textbox etc., or the built in GV columns (data bound ones, or auto generated)
Code to load the GV is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
End Sub
Sub LoadData()
Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rst As New DataTable
rst.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rst
GridView1.DataBind()
End Using
End Using
End Sub
And we now have this:
Ok, so let's do example 1 - lets color the "city" Colum in above. Note how "city" is a "bound field".
So, auto generated, or bound fields = cells collection.
So, for things like conditional formatting, even combine some columns, change color, hide show images, or whatever?
you use the GV row databound event. (and this applies well to listview, repeaters, etc.)
So, lets say for city = Edmonton, we want a light blue cell, and for city = "Edmonton", we want some light green.
So, we use the row bound event.
This code:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Select Case e.Row.Cells(3).Text
Case "Edmonton"
e.Row.Cells(3).BackColor = System.Drawing.Color.SkyBlue
Case "Banff"
e.Row.Cells(3).BackColor = System.Drawing.Color.LightGreen
End Select
End If
End Sub
And we now have this:
However, the above for "templated" colums works a bit different.
Lets say we want to highligh the description when check box = true (checked).
In that case, we can't (don't) use the cells colleciton, but for templated controls, we use find control.
Like this:
Dim cActive As CheckBox = e.Row.FindControl("chkActive")
If cActive.Checked Then
Dim lblDes As Label = e.Row.FindControl("lblDescript")
lblDes.Font.Italic = True
e.Row.Cells(4).BackColor = System.Drawing.Color.LightGray
End If
NOTE how we EVEN set the font to italic in the label control.
And now we see this:
NOTE VERY close how we use findcontrol to get those templated controls.
Last but not least - bonus:
let's highlight the whole row for active, and NOT EVEN have the check box column in the GV (but it is in the database source).
So, say this markup for the columns:
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:Label ID="lblDescript" runat="server"
Text='<%# Eval("Description") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
So, "active" check box is NOT EVEN displayed in the GV, (but, it is in the data source that feeds the gv).
So, we can do this:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim gData As DataRowView = e.Row.DataItem ' Grid data - NOT the GV row!!!!!!
If gData.Item("Active") = True Then
e.Row.Style.Add("Background-color", "LightGray") ' highlight whole row.
End If
End If
End Sub
And we now get this:
Just keep in mind that the "dataitem" (the full database row) is ONLY avaiable during the row data bind, and it WILL/DOES go out of scope once data binding is complete.
so basically using pretty much similar logics as albert's reply, I ended up catching two last rows manually and changing their colors.
protected void grdReports_PreRender(object sender, EventArgs e)
{
//finding 2 last rows, changing backcolor to the sum specified color '#5D7B9D' and the forecolor to white
//first table ( annual )
GridViewRow lastRow = grdReports.Rows[grdReports.Rows.Count - 1];
lastRow.BackColor = System.Drawing.Color.FromName("#5D7B9D");
lastRow.ForeColor = Color.White;
GridViewRow secondToLastRow = grdReports.Rows[grdReports.Rows.Count - 2];
secondToLastRow.BackColor = System.Drawing.Color.FromName("#5D7B9D");
secondToLastRow.ForeColor = Color.White;
//second table ( requested )
GridViewRow lastRowSecond = grdReports2.Rows[grdReports2.Rows.Count - 1];
lastRowSecond.BackColor = System.Drawing.Color.FromName("#5D7B9D");
lastRowSecond.ForeColor = Color.White;
GridViewRow secondToLastRowSecond = grdReports2.Rows[grdReports2.Rows.Count - 2];
secondToLastRowSecond.BackColor = System.Drawing.Color.FromName("#5D7B9D");
secondToLastRowSecond.ForeColor = Color.White;
}
so I have this code for grid view in asp.net
<asp:GridView ID="grdNewClaim" CssClass="table table-bordered table-condensed" GridLines="None" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="claim_type" HeaderText="Claim Type" />
<asp:BoundField DataField="purpose_desc" HeaderText="Purpos/Description" />
<asp:BoundField DataField="currency" HeaderText="Currency" />
<asp:BoundField DataField="amount" HeaderText="Amount" />
<asp:TemplateField HeaderText="Currency Rate">
<ItemTemplate>
<asp:TextBox ID="txtChangeCurrRate" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Converted Rate">
<ItemTemplate>
<asp:TextBox ID="txtChangeConvertedRate" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And this code to add the new row for the gridview
Private Sub addClaimProgrammatically()
Dim dt As New DataTable
Dim dr As DataRow
If grdNewClaim.Rows.Count = 0 Then
dt.Columns.Add("claim_type")
dt.Columns.Add("purpose_desc")
dt.Columns.Add("currency")
dt.Columns.Add("amount")
dt.Columns.Add("txtChangeCurrRate")
dt.Columns.Add("txtChangeConvertedRate")
dr = dt.NewRow
dr.Item("claim_type") = cmbClaimtype.Text
dr.Item("purpose_desc") = txtPurpDesc.Text
dr.Item("currency") = cmbCurrency.Value
dr.Item("amount") = txtAmmount.Text
dr.Item("txtChangeCurrRate") = lblCurrencyrate.Text
dr.Item("txtChangeConvertedRate") = lblconvertedRateMYR.Text
dt.Rows.Add(dr)
End If
grdNewClaim.DataSource = dt
grdNewClaim.DataBind()
End Sub
But for some reason the items for for both textbox just blank like this :
So any idea why? Because if I change the textbox to <asp:BoundField/> it works just fine like this
[![enter image description here][2]][2]
EDIT : create another rows in gridview
My markup is exactly the same as you. So this is my code behind. This code works just fine, however the only problem is my textbox for first row went blank. The second row is alright.
NOTE : I didn't do this on page_load.
Private Sub LoadGrid()
grdNewClaim.DataSource = dtGrd
grdNewClaim.DataBind()
End Sub
Private Sub addClaimProgrammatically()
Dim dr As DataRow
If grdNewClaim.Rows.Count = 0 Then
dtGrd.Columns.Add("claim_type")
dtGrd.Columns.Add("purpose_desc")
dtGrd.Columns.Add("currency")
dtGrd.Columns.Add("amount")
dtGrd.Columns.Add("CurrencyRate")
dtGrd.Columns.Add("ConvertedRate")
dr = dtGrd.NewRow
dr.Item("claim_type") = cmbClaimtype.Text
dr.Item("purpose_desc") = txtPurpDesc.Text
dr.Item("currency") = cmbCurrency.Value
dr.Item("amount") = txtAmmount.Text
dr.Item("CurrencyRate") = lblCurrencyrate.Text
dr.Item("ConvertedRate") = lblconvertedRateMYR.Text
dtGrd.Rows.Add(dr)
ElseIf grdNewClaim.Rows.Count > 0 Then
dtGrd.Columns.Add("claim_type")
dtGrd.Columns.Add("purpose_desc")
dtGrd.Columns.Add("currency")
dtGrd.Columns.Add("amount")
dtGrd.Columns.Add("CurrencyRate")
dtGrd.Columns.Add("ConvertedRate")
For i = 0 To grdNewClaim.Rows.Count - 1
dr = dtGrd.NewRow
dr.Item("claim_type") = grdNewClaim.Rows(i).Cells(1).Text
dr.Item("purpose_desc") = grdNewClaim.Rows(i).Cells(2).Text
dr.Item("currency") = grdNewClaim.Rows(i).Cells(3).Text
dr.Item("amount") = grdNewClaim.Rows(i).Cells(4).Text
dr.Item("CurrencyRate") = grdNewClaim.Rows(i).Cells(5).Text
dr.Item("ConvertedRate") = grdNewClaim.Rows(i).Cells(6).Text
dtGrd.Rows.Add(dr)
Next
dr = dtGrd.NewRow
dr.Item("claim_type") = cmbClaimtype.Text
dr.Item("purpose_desc") = txtPurpDesc.Text
dr.Item("currency") = cmbCurrency.Value
dr.Item("amount") = txtAmmount.Text
dr.Item("CurrencyRate") = lblCurrencyrate.Text
dr.Item("ConvertedRate") = lblconvertedRateMYR.Text
dtGrd.Rows.Add(dr)
End If
LoadGrid()
End Sub
Protected Sub btnAddClaim_Click(sender As Object, e As EventArgs) Handles btnAddClaim.Click
addClaimProgrammatically()
End Sub
The values just went missing
Thank you very much for your time !
When you use a boundfield, it works because you CAN SPECIFY which column to display.
bound field only works due to this:
Computers do not "guess" or "assume" what data column to use here.
But, when you use a templated column, and a standard control, then you need to use a expression that defines which column to use.
eg this:
<asp:TemplateField HeaderText="Currency Rate">
<ItemTemplate>
<asp:TextBox ID="txtChangeCurrRate" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
so, in above, ask this question:
Where in above does the markup KNOW which column to use?
So, you have to use a binding expression, since TextBox does not have a "boundfield" property to tell it which column to use.
Try like this:
<asp:TemplateField HeaderText="Currency Rate">
<ItemTemplate>
<asp:TextBox ID="txtChangeCurrRate" runat="server"
Text = '<%# Eval("Currency") %>'
></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
So, in above, we would be using column "Currency" for the text (or you can use "amount" or "purpose_desc" or any column from the data source.
So, your example does not work, since with a templated textbox, you have to specify the column to use - (by some how and some way). So, use the above binding expression.
Edit: data does not persist - only can add one row.
Correct - you need to save that table between each post-back, and NOT re-create the table from scratch each time, else you lose previous rows.
So, the code has to look like this:
NOTE how I defined dt at the class level (right before page load).
And note how I "restore" this dt in page load EACH time.
So, your code will become this
Markup like this:
<asp:GridView ID="grdNewClaim" CssClass="table table-bordered table-condensed"
GridLines="None" runat="server" AutoGenerateColumns="false"
ShowHeaderWhenEmpty="true" >
<Columns>
<asp:BoundField DataField="claim_type" HeaderText="Claim Type" />
<asp:BoundField DataField="purpose_desc" HeaderText="Purpos/Description" />
<asp:BoundField DataField="currency" HeaderText="Currency" />
<asp:BoundField DataField="amount" HeaderText="Amount" />
<asp:TemplateField HeaderText="Currency Rate">
<ItemTemplate>
<asp:TextBox ID="txtCRateZoo" runat="server"
Text = '<%# Eval("txtChangeCurrRate") %>'>
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Converted Rate">
<ItemTemplate>
<asp:TextBox ID="txtConvertedRate" runat="server"
Text = '<%# Eval("txtChangeCurrRate") %>' >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code now like this:
Dim dt As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
CreateTable()
LoadGrid()
Session("dt") = dt
Else
' restore table
dt = Session("dt")
End If
End Sub
Sub CreateTable()
dt.Columns.Add("claim_type", GetType(String))
dt.Columns.Add("purpose_desc")
dt.Columns.Add("currency", GetType(Double))
dt.Columns.Add("amount", GetType(Double))
dt.Columns.Add("txtChangeCurrRate", GetType(Double))
dt.Columns.Add("txtChangeConvertedRate", GetType(Double))
End Sub
Sub LoadGrid()
grdNewClaim.DataSource = dt
grdNewClaim.DataBind()
End Sub
Private Sub addClaimProgrammatically()
Dim dr As DataRow
dr = dt.NewRow
dr.Item("claim_type") = cmbClaimtype.Text
dr.Item("purpose_desc") = txtPurpDesc.Text
dr.Item("currency") = cmbCurrency.Value
dr.Item("amount") = txtAmmount.Text
dr.Item("txtChangeCurrRate") = lblCurrencyrate.Text
dr.Item("txtChangeConvertedRate") = lblconvertedRateMYR.Text
dt.Rows.Add(dr)
LoadGrid()
End Sub
Edit2: allow edits of two text box - save back to table.
So, just add this to the code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
CreateTable()
LoadGrid()
Session("dt") = dt
Else
' restore table
dt = Session("dt")
' restore grid to dt
GridToTable
End If
End Sub
Sub GridToTable()
' move any and all possile updates to grid back to our table dt
For Each gRow As GridViewRow In grdNewClaim.Rows
Dim OneRow As DataRow = dt.Rows(gRow.RowIndex)
Dim txtCurrRate As TextBox = gRow.FindControl("txtCRateZoo")
Dim txtConvertRate As TextBox = gRow.FindControl("txtConvertedRate")
OneRow("txtChangeCurrRate") = txtCurrRate.Text
OneRow("txtChangeConvertedRate") = txtConvertRate.Text
Next
End Sub
What we do is send any changes back to the dt.
This means, that any button click etc on that page will shuffle gv back to dt.
This also means that if you have a button click to jump or move on to the next page/url, then session("dt") will have the correct data.
but, since we doing this on page load, then don't use a link button, or a button with post-back url to jump to the next page (just use regular button + code behind, and say:
Response.Redirect("url to next page to jump to")
So, with above, user can now freely modify the two columns, and they will be sent back to the dt.
This also means you can loop/process the dt in code.
Say we drop a button on the form, and then behind that button we do this:
Protected Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each OneRow As DataRow In dt.Rows
Debug.Print(OneRow("currency"))
Debug.Print(OneRow("txtChangeCurrRate"))
' etc . etc.
Next
End Sub
So, we don't even have to hit the original grid, and our dt will be always updated in our session(). So, we now can work with table in code - not have to use the grid. As such, then we could have a button "continue" to move on to the next page - as along as we follow above setup, then dt will always have the latest data and edits upon a post-back.
I'm developping an asp.net Web application.
I have a table and I add rows/cells to the table through code :
<asp:Table ID="Table2" runat="server" Style="table-layout:auto;" GridLines="Both">
<asp:TableRow runat="server" Enabled="False" Font-Bold="True" HorizontalAlign="Center" VerticalAlign="Top" BackColor="#FF704C" ForeColor="Black">
<asp:TableCell runat="server">Famille</asp:TableCell>
<asp:TableCell runat="server">Editeur</asp:TableCell>
<asp:TableCell runat="server">Référence</asp:TableCell>
<asp:TableCell runat="server">Solutions</asp:TableCell>
<asp:TableCell runat="server">Nature</asp:TableCell>
<asp:TableCell runat="server">Unité</asp:TableCell>
<asp:TableCell runat="server">Usage</asp:TableCell>
<asp:TableCell runat="server">Version</asp:TableCell>
<asp:TableCell runat="server">PP net (€)</asp:TableCell>
<asp:TableCell runat="server">Quantité</asp:TableCell>
</asp:TableRow>
</asp:Table>
--
Dim tfp As New TextFieldParser(My.Settings.FilePath)
tfp.Delimiters = New String() {My.Settings.Delimiter}
tfp.TextFieldType = FieldType.Delimited
tfp.ReadLine() ' skip header
Dim Ligne As Integer = 0
While tfp.EndOfData = False
Dim fields = tfp.ReadFields()
Dim trow As New TableRow
Ligne = Ligne + 1
For i = 0 To 8
Dim tcell As New TableCell
tcell.Controls.Add(New LiteralControl(fields(i)))
trow.Cells.Add(tcell)
Next
Table2.Rows.Add(trow)
End While
Later in code, after the user click on a button, I want to get the text which is in the cell, but I always get an empty string.
MyCell = table2.rows(3).Cells(2)
? Mycell.text
""
How can I get the text which is inside the cell ?
Thank you
Ok, the main issue, is that the asp.net "table" has ONE huge big nasty issue.
Asp.net tables do NOT have viewstate nor persistence. So, in code when you add some rows, they are objects added - but NOT with viewstate.
So, your code would have to RE-RUN every time!!!!
In other words, if you run some code to add a row, you have to save that "list" or object of additions, and then on each page load - re-create, and re-add that data each time.
As a result, you are MUCH ,but I mean REALLY BEYOND WORLD poverty better off to use a control with persistence (viewstate) build in.
EVEN in that case where you want to persist the data, I STRONG suggest you persist ONLY the data table used (note how I said the data table - NOT the markup, nor the HTML markup table).
And we do not yet need to have a database to do this!!!
Of course I grasp this is just for learning, but at the end of the day? That data needs to be placed in a database. You then do the data adding, deleting, manipulation, processing against the database. If you need to show updated data as a result (say adding a new row to the database), YOU THEN RE-BIND the control on the form.
so, keep the concept of working with the data 100% separate from the control or so called UI (the web page).
Again, I 100% grasp the goal of learning, and starting out simple. The problem, is that eventually, that data WILL and NEEDS to be in a table. This will allow data base operations, or at the VERY least allow you to use code to add rows, reference a column etc.
so, I suggest you use a GridView, and THEN also create a data table (in code behind).
So, our markup now becomes this:
<asp:GridView ID="GridView1" runat="server" CssClass="table" Width="50%"
ShowHeaderWhenEmpty="true" HeaderStyle-BackColor="LightGray">
</asp:GridView>
<br />
<asp:Button ID="Button1" runat="server" Text="Add new row" CssClass="btn" />
And now our code to create the table, and also code for the add button.
We have this now:
Dim rstData As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' first page load - create a table,
' send to our grid
CreateTable
LoadGrid
Session("rstData") = rstData
Else
rstData = Session("rstData")
End If
End Sub
Sub CreateTable()
rstData.Columns.Add("Famille")
rstData.Columns.Add("Editeur")
rstData.Columns.Add("Référence")
rstData.Columns.Add("Solutions")
rstData.Columns.Add("Nature")
rstData.Columns.Add("Unité", GetType(Integer))
rstData.Columns.Add("Usage")
rstData.Columns.Add("Version", GetType(Double))
rstData.Columns.Add("PP Net(€)", GetType(Double))
rstData.Columns.Add("Quantité", GetType(Double))
End Sub
Sub LoadGrid()
GridView1.DataSource = rstData
GridView1.DataBind()
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' add a new row to our table
Dim MyNewRow As DataRow = rstData.NewRow
MyNewRow("Famille") = "this is test" ' example refernce by colum name
MyNewRow(1) = "My Editeur" ' example refernce by colum index
rstData.Rows.Add(MyNewRow) ' send new row to the table
LoadGrid() ' re-display grid to show this new row
End Sub
And when I run above, click the button, I now see this:
Note how we had much less markup, but of course a bit of extra code. However, if that table comes from a database, then we did not even have the code to "create" the table, since in most cases, that table and data would be in a database.
Other advantages?
Well, I can now format the grid, increase column lengths, even drop in a image control, or whatever I like.
In above, I did let the grid load the data table, and format the column widths, but you will often of course want to control the column widths, settings, and even what kind of control to use here.
In fact, if you have a boatload of custom controls on the grid you want, then often I suggest using a ListView in place of GridView (the hard part and learning curve is to learn when and what control to use - you have so many to choose from!!!).
So, I suggest the above.
You can then say I want the 2nd row, and cell like this:
rstData.Rows(1).Item("Famile")
rstData.Rows(1).Item(0)
Again, you can reference column(s) by number (index) or by name.
And say I want even MORE control, then say I have a grid like this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Preview">
<ItemTemplate>
<asp:Image ID="Image2" runat="server" ImageUrl = '<%# Eval("ImagePath") %>' Width="140" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="View" CssClass="btn"
CommandArgument = '<%# Eval("ImagePath") %>' OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note how we now have AutoGenerateColumns = false. That's because I want to "control" each column such as width, etc. And I wanted a image control in that "table".
So, my code to load up the above is now this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGridF()
End If
End Sub
Sub LoadGridF()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * FROM Fighters", conn)
conn.Open()
Dim rstData = New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
And now I get this:
I am using a gridview to display information on a page. The condition is that when I get Y from database result I need to bind /images/goldx.png Else /images/check.gif how can I do that I am using asp.net with vb.net as backend
<asp:GridView ID="grdLocation" runat="server" Width="100%" AutoGenerateColumns="false" >
<Columns>
<asp:TemplateField HeaderText="Monthly" HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Label ID="lblLotName" runat="server" Text='<%#Eval("is_monthly") %>'></asp:Label>
<asp:Image ID="resultImage" runat="server" ImageUrl='<%# Eval("is_monthly") == 'Y' ? "~/Images/check.gif" : "~/Images/goldx.png" %>' />
</ItemTemplate>
</asp:TemplateField>
<Columns>
</asp:GridView>
My code for binding the Gridview :
Protected Function bindLocations()
Try
Dim _ds As DataSet
If _locComp Is Nothing Then
_locComp = New LocationComponent()
End If
_ds = _locComp.GetAllLots()
If _ds.Tables(0).Rows.Count > 0 Then
grdLocation.DataSource = _ds
grdLocation.DataBind()
End If
Catch ex As Exception
End Try
End Function
Thanks for your comment and answers .
You can do this check OnRowDataBound event of GridView. Like
Private Sub grdLocation_OnRowDataBound(sender As Object, e As GridViewRowEventArgs) Handles grdLocation.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim lblLotNametxt as String = CType(e.Row.FindControl("lblLotName"),Label).Text
If lblLotNametxt = "Y" Then
CType(e.Row.FindControl("resultImage"),Image).ImageUrl = "~/Images/check.gif"
Else
CType(e.Row.FindControl("resultImage"),Image).ImageUrl = "~/Images/goldx.png"
End If
End If
End Sub
Hope this helps you.
i have this code:
Dim txt = CType(GridView1.FindControl("cnt_content"), TextBox)
txt.Attributes.Add("style", "word-wrap:break-word;")
i'm always getting that txt is an object not set to an instance of an object
that's my asp code:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
AutoGenerateColumns="False"
DataKeyNames="cnt_id">
<Columns>
<asp:TemplateField HeaderText="Content">
<EditItemTemplate>
<asp:TextBox ID="cnt_content" runat="server" Text='<%# Bind("cnt_content") %>' />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblcnt_content" runat="server" Text='<%# Bind("cnt_content") %>'></asp:Label>
</ItemTemplate>
<ItemStyle wrap="true" Width="400px" />
</asp:TemplateField>
any help?
My guess is that you are trying to find this control in the RowDataBound event, like this:
Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
End Sub
You need to only check for this control on data rows, not header or footer rows, as the control will not exist in those other types of rows, try this:
Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
' Only check in data rows, ignore header and footer rows
If e.Row.RowType = DataControlRowType.DataRow Then
' Determine if you are in edit mode or not
If GridView1.EditIndex = -1 Then
' Not in edit mode so look for label control defined in ItemTemplate of grid view
' Put logic here for label control
Else
' In edit mode so look for textbox control defined in EditItemTemplate of grid view
Dim txt = CType(GridView1.FindControl("cnt_content"), TextBox)
txt.Attributes.Add("style", "word-wrap:break-word;")
End If
End If
End Sub
It means that GridView1.FindControl("cnt_content") is returning null, which likely means that GridView does not directly contain a control called "cnt_content".