gridview display the text instead of values - asp.net

my question is:
my table consists of this values: 0, 1, 2 3
but when the gridview loads i want the text to be display instead of just those numbers.
0 = not set, 1 = low, 2 = medium, 3 = high
i could have done this like if/else condition but i just wanted to seek for a optimized sol.
here is my markup gridview:
<asp:TemplateField HeaderText="Priority" SortExpression="Priority" >
<ItemTemplate>
<asp:Label ID="lblPriority" Text='<%# DataBinder.Eval(Container.DataItem,"Priority")%>' runat="server" />
</ItemTemplate>

Assuming you don't have the display values stored in the DB anywhere, this is a way you can implement the rendering part. There may be a more maintainable way to store the lookup values, if anyone could contribute I'd appreciate it.
I wrote this in notepad since I don't have Visual Studio on my machine. Please excuse me if there are any syntax errors.
Markup:
<asp:Label ID="lblPriority" Text='<%# RenderPriority(DataBinder.Eval(Container.DataItem,"Priority")) %>' runat="server" />
Code:
Protected Function RenderPriority(ByVal dbValue As Object) As String
Dim strReturn as String = String.Empty
If Not IsDbNull(dbValue) Then
Dim intValue as Integer
If Integer.TryParse(dbValue, intValue) Then
Select Case intValue
Case 0
strReturn = "not set"
Case 1
strReturn = "low"
Case 2
strReturn = "medium"
Case 3
strReturn = "high"
End Select
Else
strReturn = dbValue.ToString()
End If
End If
Return strReturn
End Function
Edit:
After re-reading your question I get the impression you would prefer to avoid writing a specific function for this purpose in the code-behind page. If that is the case you should probably store the strings you want associated with the key values in the DB and pull them out through your SQL statement. Or, at the very least push the functionality down into a Data Access Layer. Either way ideally the GridView column will be presented with the required string by its datasource.

Why not using enumerations? Here:
Have an enumeration called Priority. Then put Description attribute on each of them, and write the display text inside the constructor of that attribute.
public enum Priority
{
[Description("not set")]
NotSet = 0,
[Description("low")]
Low = 1,
[Description("medium")]
Medium = 2,
[Description("high")]
High = 3
}
Then use Enum.ToObject method to convert the numbers (values) into their associated display value using these functions:
// An extension method for ease of use that converts an integer into enum
public static T ToEnum<T>(this int value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Input type of generic method ToEnum<T>() is not an Enum");
}
return (T)Enum.ToObject(typeof(T), value);
}
// Another extension method that gets the display text of the Description attribute of a given enum constant
public static string GetDescription(this Enum value)
{
return ((DescriptionAttribute)value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description;
}
Then in your code, you can write:
databaseValue.ToEnum<Priority>().GetDescription();

You can use the RowDataBound event of the GridView and set the value on specific condition.
Here is the complete code....
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
System.Data.DataRow dr = ((System.Data.DataRowView)e.Row.DataItem).Row;
if (dr["Priority"].ToString() == "0")
{
((Label)e.Row.FindControl("lblPriority")).Text = "not set";
}
else if (dr["Priority"].ToString() == "1")
{
((Label)e.Row.FindControl("lblPriority")).Text = "low";
}
else if (dr["Priority"].ToString() == "2")
{
((Label)e.Row.FindControl("lblPriority")).Text = "medium";
}
else if (dr["Priority"].ToString() == "3")
{
((Label)e.Row.FindControl("lblPriority")).Text = "high";
}
}
}

Related

Getting error When dt.value length is < 4

I have this code which works fine as long as as dt.Value is different to "int".
This is the line which errors:
(dt.Value.ToLower().Substring(0, 4).Equals("date"))
It works fine if dt.Value is varchar or datetime.
I provided my suggested solution at the end of this post.
// Edit
if (e.CommandName == "Edit")
{
// Get the item
RepeaterItem Item = ((RepeaterItem)((Button)e.CommandSource).NamingContainer);
// Get buttons and repeater
Button savebtn = (Button)(Item.FindControl("btnSave"));
Button editbtn = (Button)(Item.FindControl("btnEdit"));
Repeater rFields = (Repeater)(Item.FindControl("repFields"));
// Enable my fields
foreach (RepeaterItem RI in rFields.Items)
{
// Get data type
HiddenField dt = (HiddenField)(RI.FindControl("hdnDBDataType"));
// Set controls
if (RI.FindControl("chkSetting").Visible) ((CheckBox)RI.FindControl("chkSetting")).Enabled = true;
if (RI.FindControl("ddlSetting").Visible) ((DropDownList)RI.FindControl("ddlSetting")).Enabled = true;
if (RI.FindControl("txtSetting").Visible)
{
((TextBox)RI.FindControl("txtSetting")).Enabled = true;
// Check my data type
if (dt.Value.ToLower().Substring(0, 4).Equals("date")) ((CalendarExtender)RI.FindControl("extDateTime")).Enabled = true;
}
}
}
Is this a good fix ? TIA
if(dt.Value != "int" && dt.Value.ToLower().Substring(0, 4).Equals("date"))
Substring will throw an error if the second parameter is higher than the lenght of the string. What you need to do is check the length before doing the substring or use a method like #Igor suggested in the comments.
Your suggestion to check != "int" is not fullproof if let's say somehow the value is any string less than 4 characters.
(dt.Value.Length > 3 && dt.Value.ToLower().Substring(0, 4).Equals("date"))
I will also put #Igor suggestion here because it is also fullproof:
(dt.Value.StartsWith("date", StringComparison.OrdinalIgnoreCase)

Compare Validator for two dates

I have two labels and two text boxes, a Compare validator and a button.
I need it to compare two dates (rental date , return date ) and when the rental date is less or equal to return date are the same. No validation message.
While when when the rental date is less than the return date, display an input error message.
The compare validator has been set with :
controltocompare : txtrental,
controltovalidate: txtreturndate,
operator :greater than equal,
type:date,
errormessage: return date must be greater or equal than rental date,
I am not sure how to get the btn to display it ?
You need to set the property "CausesValidation" of your button to "true" to trigger validation on its click.
Make sure the CompareValidator has runat="server"
Create a method to display message.
private void AlertBox(string Msg)
{
string s = "alert('" + Msg + "')";
ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "ckey", s, true);
}
find the code to validate and throw alert message.
if (!String.IsNullOrEmpty(txtrental.Text) && !String.IsNullOrEmpty(txtreturndate.Text))
{
DateTime ssSD = Convert.ToDateTime(txtrental.Text);
DateTime qsED = Convert.ToDateTime(txtreturndate.Text);
int chktxtfd1_sd = ssSD.CompareTo(qsSD);
if ((chktxtfd1_sd == 0 || chktxtfd1_sd == -1) )
{
//do something bcoz condition is true
}
else
{
lvflag = false;
AlertBox("date must be greater or equal than rental date");
}
}
If you find it useful, please mark it as your answer else let me know...

grid View footer total in asp.net [duplicate]

protected void inderGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
decimal rowTotal = Convert.ToDecimal
(DataBinder.Eval(e.Row.DataItem, "DC_No_Decimal"));
//grdTotal = grdTotal + rowTotal;
grdTotal += rowTotal;
}
if (e.Row.RowType == DataControlRowType.Footer)
{
Label lbl = (Label)e.Row.FindControl("lblTotal");
e.Row.Cells[3].Text = grdTotal.ToString("c");
//lbl.Text = grdTotal.ToString("c");
}
}
from the above code i m getting total for every page in the grid view. Instead of getting total to every page i need all page total at the end of the grid view footer. Help Immediatly.
Thanks in advance
If you want the total of ALL pages, and for the footer to only appear on the last page, then you can't calculate the totals how you are doing.
At the moment your looping through every row on the gridview. If you are using paging the gridview won't be showing all the rows, so the total won't be correct.
Are you paging with a PagedDataSource or are you limiting the records returned from SQL etc? If you are using a DataSet and a PagedDataSource you'll be able to find the total from the DataSet (as this will contain all the records). Otherwise, you'll have to create a second query to calculate the total.
Then in terms of displaying the values in the footer, you'll have to add an IF statement to your ItemDataBound event to only display this if its the final page.
If you trying to display the record summery, please look this one about Displaying Summary Information in the GridView's Footer
What I do is setup the following in the code behind (This is just an example column):
int totalCallsTaken = 0;
public int CallsTaken(int value)
{
totalCallsTaken += value;
return value;
}
public int CallsTakenTotal()
{
return totalCallsTaken;
}
Then in the ASPX page I put the following template field in:
<asp:TemplateField HeaderText="Calls Taken" FooterStyle-Font-Bold="true">
<ItemTemplate>
<%#CallsTaken(Convert.ToInt32(Eval("CallsTakenCount").ToString())).ToString("N0")%>
</ItemTemplate>
<FooterTemplate>
<%#CallsTakenTotal().ToString("N0")%>
</FooterTemplate>
</asp:TemplateField>
I hope that helps, Ian.
Noddy but you can try one more check in the if condition.
if(e.Row.RowType == DataControlRowType.Footer && inderGrid.PageCount == inderGrid.PageIndex + 1)
{
//code here.
}
// Try this
if(e.Row.RowType == DataControlRowType.Footer && inderGrid.PageCount == inderGrid.PageIndex + 1)
{
for (int i=0; i< inderGrid.Rows.Count; i++)
{
var currentRowCellVal = Convert.ToDecimal(inderGrid.Rows[i].Cells[0].Text);
grdTotal += currentRowCellVal;
}
e.Row.Cells[3].Text = grdTotal.ToString("c");
}
Just to be certain I'm understanding, you're saying you have a grid with say 100 items, but only 25 are shown at any given time. Then you want the footer to only display the sum of those 25 items that are displayed on the page.
There's a couple of options that you can do here for this:
1) Use JavaScript to calculate the total after the page has been rendered.
2) use intelligent SQL to only return those particular rows that you're wanting to display on the grid--and then keep your grid the same
3) calculate the visible rows in your code, and only add them when you need them. Remember, you know in the code behind which Grid.PageIndex you're on as well as how many items each page has. With this knowledge, you should be able to determine via the row index if any given datarow will be rendered to the screen.
You need to generate all records total using the actual data.
If you are doing paging at the data-sire (database) side then you have total at the data-sore side - you may use the same SP that returns a page-full of records to return the total of all records. If you are retrieving all records and doing paging at the web server side then you may use the retrieve data-source to do the totaling.
From optimization perspective, you can compute the total once and store it in the view-state.
If you wish to show the footer on the last row then you can use ShowFooter - set it to true only on the last page.
All you need to do is check whether your row is in the current page and do the calculation.
For example, something like this:
if (e.Row.RowType == DataControlRowType.DataRow)
{
decimal rowTotal = Convert.ToDecimal
(DataBinder.Eval(e.Row.DataItem, "DC_No_Decimal"));
if (e.Row.DataItemIndex >= inderGrid.PageIndex * inderGrid.PageSize
&& e.Row.DataItemIndex < inderGrid.PageIndex * inderGrid.PageSize + inderGrid.PageSize)
grdTotal += rowTotal;
}
Try this,
using System.Linq;
dt.AsEnumerable().Select(x => x.Field<decimal>("DC_No_Decimal")).Sum().ToString();
you can use the code like this for get sum at the footer
gv.DataSource = dt;
gv.Columns[2].FooterText = dt.Rows.Count > 0 ? dt.AsEnumerable().Select(x => x.Field<decimal>("DC_No_Decimal")).Sum().ToString() : "";
gv.DataBind();

Insert a control before another control inside a ItemDataBound event

I tried to Solution suggested here, but it didn't work in my case. using Page.Controls.IndexOf() for any of the elements on my page, when called in the ItemDataBound event method, returns -1.
I need to insert a linebreak based on certain conditions for stuff generated by my Data repeater. Here is the method:
private String lastCharacter = "";
public void users_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
HyperLink link = (HyperLink)e.Item.FindControl("micrositeLink");
Tuple<String, String> user = (Tuple<String, String>)e.Item.DataItem;
link.NavigateUrl = "/" + user.Item1;
link.Text = user.Item2;
// makes a break in the data when going from one bunch of data to another.
if (user.Item1.Length >= 2)
{
if (lastCharacter == "")
lastCharacter = user.Item1[1].ToString().ToLower();
else if (lastCharacter != user.Item1[1].ToString().ToLower())
{
HtmlGenericControl lineBreak = new HtmlGenericControl("br");
if (Page.Controls.IndexOf(link) >= 0)
Page.Controls.AddAt(Page.Controls.IndexOf(link), lineBreak);
lastCharacter = user.Item1[1].ToString().ToLower();
}
}
}
The bound data is a list of users in my system with names beginning with a particular letter. My goal is to further sub-divide this data with a line break between groups of data that have the same second letter. For instance:
AaPerson Aarad AaStuff
Aathing
AbItem AbStuff
Acan Achandle
To me, inserting a line break before the elements where the second letter changes is the obvious solution, but other suggestions are also appreciated.
Try using e.Item.Controls.IndexOf instead:
if (e.Item.Controls.IndexOf(link) >= 0)
e.Item.Controls.AddAt(e.Item.Controls.IndexOf(link), lineBreak);

Error: FormatException was unhandled by user code in Linq how to solve?

Look please below this codes throw me : FormatException was unhandled by user code
Codes:
satis.KDV = Decimal.Parse((from o in genSatisctx.Urun where o.ID == UrunID select o.Kdv).ToString());
How can i rewrite linq query?
You are calling ToString on the query rather than a single result. Even though you may expect only one value to match your query, it will not return just a single value. You have to instruct it to do so using Single, First, Last or the variations of these that also return a default value (SingleOrDefault, FirstOrDefault, LastOrDefault).
In order to avoid an exception, you could change it to use Decimal.TryParse or you could change your code to use a default value if the LINQ query returns something that won't parse properly. I'd recommend the former or a combination.
Note that in the following example, I have added the call to SingleOrDefault. This ensures that only one value is parsed, even if no value is found, and that if there are multiple results, we get an exception (i.e. it enforces that we get exactly zero or one result to the query).
decimal parsedValue;
if (Decimal.TryParse(
genSatisctx
.Urun
.Where(o => o.ID == UrunID)
.Select(o=>o.Kdv)
.SingleOrDefault()
.ToString(), out parsedValue))
{
satis.KDV = parsedValue;
}
You're calling ToString() on an IQueryable<T> - what did you expect the string to be? It's very unlikely to be anything which can be parsed as a decimal number!
My guess is that you want to call First() or Single(), but we can't really tell without more information. What's the type of o.Kdv?
I suspect you either want:
satis.KDV = (from o in genSatisctx.Urun
where o.ID == UrunID
select o.Kdv).First();
or
string kdvString = (from o in genSatisctx.Urun
where o.ID == UrunID
select o.Kdv).First();
decimal kdv;
if (decimal.TryParse(kdvString, out kdv))
{
satis.KDV = kdv;
}
else
{
// What do you want to do if it's not valid?
}
When I use debug mode I see the data is update when over mouse, after end of this method ( it's show this message [input string was not in a correct format]
/* protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
try
{
TextBox name = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtEditName");
SqlDataSource2.UpdateParameters["Name"].DefaultValue = name.ToString();
TextBox age = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtEditAge");
SqlDataSource2.UpdateParameters["Age"].DefaultValue = age.ToString();
TextBox birthday = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtEditBirthday");
SqlDataSource2.UpdateParameters["Birthday"].DefaultValue = birthday.ToString();
DropDownList country = (DropDownList)GridView1.Rows[e.RowIndex].FindControl("DropEditCountry");
SqlDataSource2.UpdateParameters["CountryID"].DefaultValue = country.SelectedValue;
TextBox mobile = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtEditMobile");
SqlDataSource2.UpdateParameters["Mobile_No"].DefaultValue = mobile.ToString();
SqlDataSource2.Update();
}
catch (Exception j)
{
j.Message.ToString();
}
}
/* }

Resources