if statement in gridview template filed - c#

I have a gridview. its data source is a datatable that is loaded from the database.
In this gridview, i have a template column. The content of this column is not directly pulled from the database but instead, i use the id of the current item to make a name and look for that name in a directory of images. The template field is:
<asp:TemplateField>
<itemtemplate>
<img src='../user/images/<% =itemType %><%# DataBinder.Eval(Container.DataItem, "id") %>.jpg?'
alt='<%# DataBinder.Eval(Container.DataItem, "Title") %>' />
</itemtemplate>
</asp:TemplateField>
Not all the items have images so I would like to check if this file exists. If it does, I'd like to use the above code to place it, if it doesn't i'd like to leave the field empty.
In the .cs file this is a matter of an if statement with the condition set to File.Exist(). But I could not find the syntax to do it in the .aspx file.
Is this possible and if so how?
Thanks.

you could code this behavior on the RowDataBound event. somethink like the below
Remember to make the image runat="server"
protected void GridViewProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType = DataControlRowType.DataRow){
if(!File.Exist(yourFileName){
//hide the image
var img=e.Row.FindControl("theImageId");
img.visible=false;
}
}
}
I think you should go for the above solution.
anyway Just add the below
<asp:TemplateField>
<itemtemplate>
<img src='../user/images/<% =itemType %><%# DataBinder.Eval(Container.DataItem, "id") %>.jpg?'
alt='<%# DataBinder.Eval(Container.DataItem, "Title") %>'
<%= File.Exists("yourFileName")? string.Empty : "style='display: none'" %> />
</itemtemplate>
</asp:TemplateField>

img tag has an event called onerror. So, if your requirement is to do something if the image is not found, do something like this.
onerror="this.src='Images/default.png'"

Related

Pass parameter from Gridview column to Javascript

I need to pass an argument (which comes from my database) from a radgrid view column to my javascript (which opens a dialog box window). However, I can't put the "bind("Id")" as a parameter from where I call the javascript as href.
In simpler words, I am looking for a way to pass <% Bind("Id")%> to the javascript, OpenMyWindow, call instead of the hardcoded, 111, right now.
<telerik:GridTemplateColumn UniqueName="Meet" DataField="Subject" HeaderText="Meet">
<ItemTemplate>
<div style="text-align: center">
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# Bind("Subject") %>' href="javascript: OpenMyWindow(111);" Width="30%">
</asp:LinkButton>
</div>
</ItemTemplate>
</telerik:GridTemplateColumn>
When I try "OnClick" instead of "href", my popup dialog box closes instantly and doesn't stay opened.
Try using "OnClientClick" and return false from your javascript method to prevent post back.
Alternatively. You could use a method passing in the DataIten. Then output an anchor tag created anyway you like:
<%# formatOpener(Container.DataItem) %>
With code behind of:
protected string formatOpener(object item)
{
ObjectType myObj = (ObjectType)item;
return String.Format("<a href=\"javascript:OpenMyWindow({0});\" width=\"30%\"/>{1}</a>", myObj.ID, myObj.subject);
}
I think you don't need a LinkButton, you could achieve it with an asp:HyperLink (which renders as a a tag):
<asp:HyperLink ID="HyperLink1" runat="server" Text='<%# Eval("Subject") %>' NavigateUrl='<%# "javascript: OpenMyWindow(" + Eval("ID").ToString() + ");" %>'></asp:HyperLink>
Also, don't use Bind if you don't need it, for displaying purposes always use Eval.
User HyperLink control instead and try setting the NavigateUrl property of the HyperLink this way:
<asp:HyperLink ID="hlLink" runat="server" Text='<%# Bind("Subject") %>' NavigateUrl='<%#Eval("Id", "javascript: OpenMyWindow({0});")%>'>
hope it helps./.
I finally figured out and solved this issue. Actually, somebody told me on the other post that, CommandArgument is completely a server-side property and doesn't render any html attribute. So I can't change any button's attribute and fire click on it. I finally made "Id" come through the code behind and made it work.
aspx code
<telerik:GridButtonColumn UniqueName="Subject" DataTextField="Subject" HeaderText="Meeting">
<HeaderStyle Width="30%" />
<ItemStyle HorizontalAlign="Center" />
</telerik:GridButtonColumn>
Code Behind
var subjectLink = meetingRow["Subject"].Controls[0] as LinkButton;
subjectLink.Attributes.Add("onClick", "javascript: return OpenMyWindow('" + meetingId + "')");

How to access Dataset from.cs to .aspx using eval()

I am coding Gridview programmatically.
I have dataset in code behind part(.cs),when i am trying to access the dataset in .aspx page using Eval() "Error Creating Control" error is coming.
Is it the Right way using Eval()?
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblGridTier" runat="server" Text='<%#Eval(dt.Tables[0].Columns["Tier"])%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
If you are doing something like this in the code behind to bind the GridView (and you actually should do something like this):
DateSet ds = ...
GridView1.DataSource = ds;
GridView1.DataBind();
then the correct way to use eval is to give it just the name of the column you want to show.
Text='<%#Eval("Tier")%>'
ok please note html is rendered first then your code behind file is called. Now here dataset is null (not yet created) when HTML is being rendered dataset is null so control will not be created and an exception will be thrown. You can use this work around on Page_Load you can set text property of label or check here if dataset is null then don't assign value using Eval. Hope it will help.
Eval function evaluates fields directly from the selected table of datasource which your grid is bound with. A couple of examples as follows:
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblSomeField" runat="server" Text='<%# Eval("field1")%>'></asp:Label>
<asp:Image ID="lblImageLink" runat="server" ImageUrl='<%# Eval("imagefield", "http://somelink.com/images/{0}")%>' />
<asp:HyperLink ID="lblMember" runat="server" NavigateUrl='<%# "/member.aspx?id=" + Eval("id") %>' Text='<%# Eval("membername") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>

ASP.Net Repeater Eval in an If statement

So I've been looking around for a good answer to this question, but haven't really found anything useful. Hopefully someone can shed some light on this for me.
Basically, I have a repeater that is backed by a database table. Inside the ItemTemplate for this repeater, I have some HTML elements that are populated with properties from each item in the list. Pretty standard stuff. However, there is a possibility that one of the items could be null. In that case, it would make sense for me to put some sort of if (blah != null) logic around the offending code. The only problem is, when I've tried to do so, ASP throws up on me, telling me that I can't use an if statement inside of <%# %>.
My question to the masses is this: if you can't use an if statement inside of <%# %>, then how are you supposed to do conditional logic based on the values of each item?
I know that you can call your own methods inside the repeater, but that won't work for what I'm trying to do.
Below is what I'm trying to accomplish, to better illustrate my point.
<asp:Repeater runat="server" ID="repeater">
<ItemTemplate>
<div class="item-wrap">
<% if(Eval("imageUrl") != null) { %>
<div class="plan-img">
<asp:Image runat="server" ImageUrl='<%# Eval("imageUrl") %>'/>
</div>
<% } %>
</div>
</ItemTemplate>
</asp:Repeater>
inside your ItemTemplate write the markup like this:
<asp:Panel runat="server" Visible='<%# Eval("imageUrl") != null %>'>
<asp:Image runat="server" ImageUrl='<%# Eval("imageUrl") %>'/>
</asp:Panel>
Basically you can't mix code <% with databinding constructs <%#.
My advice would be to add the following property in your CodeBehind:
protected YourClass DataItem
{
get
{
return (YourClass)this.Page.GetDataItem();
}
}
and then write the markup without Eval():
<asp:Image runat="server" ImageUrl='<%# DataItem.imageUrl %>'/>
You're supposed to generate the same content for every item in the template. If you don't need to use it for a particular item just set it's visibility to false in the binding events.

GridView trouble in .Net

i think this maybe an easy one...
I have a Gridview, bound to a dataSource with this query:
select userid, name, phone from users
I need to change the content of the Name cell to a link, like so:
User's Name
so OnRowDataBound i'm doing this:
e.Row.Cells[1].Text = "" + e.Row.Cells[1].Text + "";
It all works fine this way. My problem is that i don't want to display the UserId column in the Gridview, but when i attribute it (asp attribute or server-side) Visible="false" to the BoundField UserId, i can't capture it's value to build the Name Cell.
Thanx for your help
Make your gridView to use template items instead of simple grivdiew column.
<asp:TemplateField HeaderText="FirstName" SortExpression="FirstName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstName")%>'>
</asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
You can find a nice intro Here
Agree with Jani, this should be done with a template field. If you really need to do it the other way, see Can data be kept in a dynamically bound GridView's invisible fields?.
you can set the visibility on the onrowdatabound event

How to create conditional content within a databound Repeater

I'm setting up a User Control driven by a XML configuration. It is easier to explain by example. Take a look at the following configuration snippet:
<node>
<text lbl="Text:"/>
<checkbox lbl="Check me:" checked="true"/>
</node>
What I'm trying to achieve to translate that snippet into a single text box and a checkbox control. Of course, had the snippet contained more nodes more controls would be generated automatically.
Give the iterative nature of the task, I have chosen to use Repeater. Within it I have placed two (well more, see bellow) Controls, one CheckBox and one Editbox. In order to choose which control get activate, I used an inline switch command, checking the name of the current configuration node.
Sadly, that doesn't work. The problem lies in the fact that the switch is being run during rendering time, long after data binding had happened. That alone would not be a problem, was not for the fact that a configuration node might offer the needed info to data bind. Consider what would happen if the check box control will try to bind to the text node in the snippet above, desperately looking for it's "checked" attribute.
Any ideas how to make this possible?
Thanks,
Boaz
Here is my current code:
Here is my code (which runs on a more complex syntax than the one above):
<asp:Repeater ID="settingRepeater" runat="server">
<ItemTemplate>
<%
switch (((XmlNode)Page.GetDataItem()).LocalName)
{
case "text":
%>
<asp:Label ID="settingsLabel" CssClass="editlabel" Text='<%# XPath("#lbl") %>' runat="server" />
<asp:TextBox ID="settingsLabelText" Text='<%# SettingsNode.SelectSingleNode(XPath("#xpath").ToString()).InnerText %>'
runat="server" AutoPostBack="true" Columns='<%# XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"#width",20) %>'
/>
<% break;
case "checkbox":
%>
<asp:CheckBox ID="settingsCheckBox" Text='<%# XPath("#lbl") %>' runat="server"
Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("#xpath").ToString())).HasAttribute(XPath("#att").ToString()) %>'
/>
<% break;
} %>
</ItemTemplate>
</asp:Repeater>
One weekend later, here is what I came with as a solution. My main goal was to find something that will both work and allow you to keep specifying the exact content of the Item Template in markup. Doing things from code would work but can still be cumbersome.
The code should be straight forward to follow, but the gist of the matter lies in two parts.
The first is the usage of the Repeater item created event to filter out unwanted parts of the template.
The second is to store decisions made in ViewState in order to recreate the page during post back. The later is crucial as you'll notice that I used the Item.DataItem . During post backs, control recreation happens much earlier in the page life cycle. When the ItemCreate fires, the DataItem is null.
Here is my solution:
Control markup
<asp:Repeater ID="settingRepeater" runat="server"
onitemcreated="settingRepeater_ItemCreated"
>
<ItemTemplate>
<asp:PlaceHolder ID="text" runat="server">
<asp:Label ID="settingsLabel" CssClass="editlabel" Text='<%# XPath("#lbl") %>' runat="server" />
<asp:TextBox ID="settingsLabelText" runat="server"
Text='<%# SettingsNode.SelectSingleNode(XPath("#xpath").ToString()).InnerText %>'
Columns='<%# XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"#width",20) %>'
/>
</asp:PlaceHolder>
<asp:PlaceHolder ID="att_adder" runat="server">
<asp:CheckBox ID="settingsAttAdder" Text='<%# XPath("#lbl") %>' runat="server"
Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("#xpath").ToString())).HasAttribute(XPath("#att").ToString()) %>'
/>
</asp:PlaceHolder>
</ItemTemplate>
</asp:Repeater>
Note: for extra ease I added the PlaceHolder control to group things and make the decision of which controls to remove easier.
Code behind
The code bellow is built on the notion that every repeater item is of a type. The type is extracted from the configuration xml. In my specific scenario, I could make that type to a single control by means of ID. This could be easily modified if needed.
protected List<string> repeaterItemTypes
{
get
{
List<string> ret = (List<string>)ViewState["repeaterItemTypes"];
if (ret == null)
{
ret = new List<string>();
ViewState["repeaterItemTypes"] = ret;
}
return ret;
}
}
protected void settingRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
string type;
if (e.Item.DataItem != null)
{
// data binding mode..
type = ((XmlNode)e.Item.DataItem).LocalName;
int i = e.Item.ItemIndex;
if (i == repeaterItemTypes.Count)
repeaterItemTypes.Add(type);
else
repeaterItemTypes.Insert(e.Item.ItemIndex, type);
}
else
{
// restoring from ViewState
type = repeaterItemTypes[e.Item.ItemIndex];
}
for (int i = e.Item.Controls.Count - 1; i >= 0; i--)
{
if (e.Item.Controls[i].ID != type) e.Item.Controls.RemoveAt(i);
}
}
You need something that looks more like this:
<ItemTemplate>
<%# GetContent(Page.GetDataItem()) %>
</ItemTemplate>
And then have all your controls generated in the code-behind.

Categories