Can't set Visible attribute in ASP.NET Panels - asp.net

I am having trouble with visible attribute of an ASP.NET Panel control. I have a page that calls a database table and returns the results in a datagrid.
Requirements
If some of the returned values are null I need to hide the image that's next to it.
I am using a Panel to determine whether to hide or show the image but am having trouble with the statement:
visible='<%# Eval("addr1") <> DBNull.Value %>'
I have tried these as well:
visible='<%# Eval("addr1") <> DBNull.Value %>'
visible='<%# IIf(Eval("addr1") Is DbNull.Value, "False","True") %>'
Code is below:
<asp:TemplateField >
<ItemTemplate>
<%# Eval("Name")%>
<p>
<asp:Panel runat="server" ID="Panel1"
visible='<%# Eval("addr1") <> DBNull.Value %>'>
<asp:Image Id="imgHouse" runat="server"
AlternateText="Address" SkinId="imgHouse"/>
</asp:Panel>
<%# Eval("addr1") %><p>
</ItemTemplate>
</asp:TemplateField>
What am I doing wrong?
Edit
If I use visible='<%# IIf(Eval("addr1") Is DbNull.Value, "False","True") %>'
I get the following error:
Compiler Error Message: CS1026: ) expected

try:
<%# String.IsNullOrEmpty(DataBinder.Eval(Container.DataItem,"addr1").ToString()) #>

try comparing the result of the eval to blank as opposed to null.

This would probably be easier to accomplish with server side code.
Handle the RowDataBound event in your grid (assuming you're using gridview, for DataGrid it's ItemDataBound) and then do this:
public void grid1_RowDataBound(object sender, GridViewRowDataBoundEventArgs e)
{
if(e.Row.RowType == RowType.DataRow)
{
object itemFromDb = e.Row.DataItem; //you'll need to cast this to your type
Panel p = (Panel)e.Row.FindControl("myPanel");
if(itemFromDb.SomeItem == null)
p.Visible = false;
}
}
This is off of the top of my head, I might have a syntax error or 2 in there. But you get the idea.

Hmmm...
visible='<%# IIf(Eval("addr1") Is DbNull.Value, "False","True") %>'
Should work. What error are you getting?

Related

How to get Text box value from Grid view header template?

I want grid view header template textbox value. I write code for getting value but it return null.
<asp:Button ID="btngetLocationDate" runat="server" Text="Get Filtered Data" OnClick="getTextBoxValue"></asp:Button>
<asp:TemplateField HeaderText="Mobile Number">
<HeaderTemplate>
Mobile Number:
<asp:TextBox ID="txtMobilenumber" runat="server" ></asp:TextBox>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblmobile" runat="server" Text='<%# Eval("Mobile Phone") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
And On the code behind.cs i write that code but it returns null
protected void getTextBoxValue(object sender, EventArgs e)
{
//TableCell cell1 = TrackerGrid.HeaderRow.Cells[0];
TextBox mobilenumber = (TrackerGrid.HeaderRow.FindControl("txtMobilenumber") as TextBox) ;
string mobile = mobilenumber.Text;
How can I resolve this ? please help me!
I've just had a similar problem by trying to get textbox text from the footer row. I'm not sure if this is the best way to get around this problem but this should work if FindControl() successfully assigns the textbox.
TextBox mobilenumber = (TrackerGrid.HeaderRow.FindControl("txtMobilenumber") as TextBox);
string mobile = Request.Form[mobilenumber.UniqueID];
EDIT: As VDWWD commented, Request.Form is a bad practice. But for my particular usage I couldn't find any other way to get the data from a textbox on button click due to my unorganized postbacks.

Passing CommandArguement to LinkButton from variable

I have seen many resources on SO that say that I can use following syntax to pass value to CommandArguement of `LinkButton'
<%forearch(var comment in Comments){%>
<asp:LinkButton ID="del" CommandArguement='<%= comment.CommentId%>' onCommand="delete_click" Text="Delete"/>
<%}%>
But when I write this in my ascx file and click on the link the value passed to command argument is "<%=comment.CommentId%>" instead of commentId itself. Please guide what am I doing wrong?
Edit 1
based on answers and comments, I have moved to use repeater instead of foreach and plain code. Here is the code I have come up with
<asp:Repeater ID="commRepeater" SelectMethod="GetPageComments" runat="server">
<ItemTemplate>
<p>
<%#Eval("Comment") %>
<%if(Page.User.Identity.IsAuthenticated && Page.User.Identity.GetUserId() == Eval("UserId")){ %>
<span>
<asp:LinkButton Text="Edit" runat="server" ID="EditLink" CommandArgument='<%#Eval("CommentId")%>' OnClick="Update_Comment" />
<asp:LinkButton Text="Delete" runat="server" ID="DeleteLink" CommandArgument='<%#Eval("CommentId")%>' OnClientClick="if (!confirm('Are you sure you want delete?')) return false;" OnCommand="Delete_Comment" />
</span>
<%} %>
</p>
</ItemTemplate> </asp:Repeater>
you can see that I am trying to show the edit and delete links if user is logged in and his Id matches with user who commented but it tells me that I can on use Eval in databound controls. how would I hide/show edit/delete links conditionally within repeater
You could simply use codebehind, for example in Page_Load:
protected void Page_Load(Object sender, EventArgs e)
{
if(!IsPostBack)
{
del.CommandArgument = comment.CommentId;
}
}
Maybe a better approach would be to use the Comments-collection(which seems to be a list or array of a custom class) as DataSource of a Repeater(or other web-databound control). Then you can add the LinkButtons to the Itemtemplate.
You can then either use ItemCreated or ItemDataBound events of the repeater in codebehind or inline ASP.NET tags to bind the CommandArgument.
For example:
CommandArguement='<%# DataBinder.Eval( Container.DataItem, "CommentId" ) %>'
What you are doing currently is not recommended and is highly error prone. You can easily achieve this with ASP.NET Repeater control like this:-
<asp:Repeater ID="MyRepeater" runat="server">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Eval("CommentId") %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
In Page_Load simply bind it:-
if (!Page.IsPostBack)
{
MyRepeater.DataSource = CommentsRepository();
MyRepeater.DataBind();
}
Or Else if you are have ASP.NET 4.5 then use strongly type Data Bound controls like this:-
<asp:Repeater ID="MyRepeater" runat="server" ItemType="MyNamespace.Comment"
SelectMethod="MyRepeater_GetData">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Item.CommentId %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
And you method in code behind should be something like this(just for Demo):-
public IEnumerable<MyNamespace.Comment> MyRepeater_GetData()
{
return new List<Comment>
{
new Comment { CommentId =1, Name= "foo"},
new Comment { CommentId =2, Name= "bar"},
};
}

Populating a variable with DetailsView textbox data value

When an ASP.Net DetailsView data is first displayed, can you tell me how to populate the variable shown in this coding?
I already tried this in the code-behind file but was shown an error that:
Object reference not set to an instance of an object.
This is the coding:
Protected Sub DetailsViewDetails_DataBound(sender As Object, e As EventArgs) Handles DetailsViewDetails.DataBound
Dim txtOriginalRegistrationFee As TextBox
If DetailsViewDetails.CurrentMode = DetailsViewMode.Edit Then
txtOriginalRegistrationFee = FindControl("TextBoxRegistrationFee")
If String.IsNullOrEmpty(txtOriginalRegistrationFee.Text) = False Then
MsgBox(txtOriginalRegistrationFee)
End If
End If
End Sub
This is from the aspx file:
<asp:TemplateField HeaderText="RegistrationFee" SortExpression="RegistrationFee">
<EditItemTemplate>
<asp:TextBox ID="TextBoxRegistrationFee" runat="server" Text='<%# Eval("RegistrationFee") %>'></asp:TextBox>
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID="TextBoxRegistrationFee" runat="server" Text='<%# Bind("RegistrationFee") %>'></asp:TextBox>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="LabelRegistrationFee" runat="server" Text='<%# Bind("RegistrationFee", "{0:c}") %>'></asp:Label>
</ItemTemplate>
<ItemStyle ForeColor="Blue" />
</asp:TemplateField>
* Update *
I tried using this coding updated based on your help but still get the "Object reference not set to an instance of an object." error when clicking the edit button of the DetailsView.
The FindControl function needs a control to search otherwise it will be searching the page (or content) level controls.
Try
txtOriginalRegistrationFee = DetailsViewDetails.FindControl("TextBoxRegistrationFee")
By the way your line with the MsgBox function will not work either. MsgBox is for windows forms and will not work on the web. You must use javascript for that type of functionality. Plus, that function takes a string, not a control.
I don't work in VB so bear with me.... The template is only rendered if your details view is in insert mode.
Dim txtOriginalRegistrationFee As TextBox
If DetailsViewDetails.CurrentMode = DetailsViewMode.Insert Then
txtOriginalRegistrationFee = FindControl("TextBoxRegistrationFee")
If String.IsNullOrEmpty(txtOriginalRegistrationFee.Text) = False Then
MsgBox(txtOriginalRegistrationFee)
End If
End If

Calling a property or member function of a string object inside of a ListView

I'm having some trouble calling a property or a method on a databound string object inside of a ListView. See this example:
<asp:ListView runat="server" ID="FullInfoListView">
<LayoutTemplate>
<table class="tablestripe" width="100%">
<asp:Placeholder runat="server" ID="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr valign="top" runat="server" Visible='<%# !string.IsNullOrEmpty((string)Eval("Phone")) %>'>
<td><strong>Phone:</strong></td>
<td><span runat="server" Visible='<%# ((string)Eval("Phone")).Length == 4 %>'>x</span><%# Eval("Phone") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
This line:
<%# ((string)Eval("Phone")).Length == 4 %>'>
is what is giving me trouble. If I remove the .Length everything works fine. If I leave it in there my code throws an "Object reference not set to an instance of an object." exception on the line where I call the DataBind() method on the ListView in my code behind. This same behavior occurs with .ToLower() as well.
EDIT
I think I got this figured out. Thanks for those of you who suggested moving this out to a method in the code behind to help with debugging. The problem was related to a null reference...go figure :) I thought that if the table row wasn't visible that none of the logic inside would get evaluated, but I think due to the fact that it is databound the logic is evaluated anyway. So simply changing the above line to the following fixed the problem:
<%# Eval("Phone") != null && ((string)Eval("Phone")).Length == 4 %>'>
I would consider using a Label instead of a <span>. Instead of casting it to string, just use the ToString() function instead, and wrap the entire expression in parentheses to ensure that it's evaluating as a boolean:
<asp:Label ID="Label1" runat="server" Visible='<%# (Eval("Phone").ToString().Length >= 4) %>' Text="X" />
If the above doesn't fix your problem, you can always add a method in the code behind to do this:
<asp:Label ID="Label1" runat="server" Visible='<%# CheckLength(Eval("Phone").ToString()) %>' Text="X" />
Code-behind:
public bool CheckLength(string value)
{
return value.Length >= 4;
}
Move the compound code to code-behind method. For example the
'<%# ((string)Eval("Phone")).Length == 4 %>'
becomes
'<%# IsPhoneSpanVisible( (string)Eval( "Phone" ) ) %>'
with
protected bool IsPhoneSpanVisible( string Phone )
{
// provide your logic here
}
This way you'll be easily able to debug your code.

ASP.NET GridView ItemTemplate

OK I have a GridView and there is a column that I want to be a link if a file exists, otherwise I just want it to be a label. Right now I am changing the controls on RowDataBound event handler using the Row passed in the args. I am not a big fan of this as I am hard coding the column ID, and if it ever changes I will need to remember to change this code. I was hoping I could do a conditional in the asp code to add a link if a property value is not null otherwise add a label. Is this possible? Any different solutions?
I would like something like this:
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<%# if (Eval("LogFileName") == null)
<%#{
<asp:LinkButton ID="LogFileLink" runat="server" CommandArgument='<% #Eval("LogFileName") %>' CommandName="DownloadLogFile" Text='<%# Blah.NDQA.Core.Utilities.GetEnumerationDescription(typeof(Blah.NDQA.Core.BatchStatus), Eval("Status")) %>'>
<%# }
<%# else
<%#{
<asp:Label ID="LogFileLabel" runat="server"Text='<%# Blah.NDQA.Core.Utilities.GetEnumerationDescription(typeof(Blah.NDQA.Core.BatchStatus), Eval("Status")) %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
You can continue to use RowDataBound event but in your aspx you add:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
In your C# code something like that:
if (LogFileName) {
LinkButton ctrl = new LinkButton();
ctrl.CommandArgument= ...;
ctrl.CommandName= ...;
} else {
Label ctrl = new Label();
ctrl.Text= ...;
}
// You have to find the PlaceHolder1
PlaceHolder1.Controls.Add(ctrl);
In this way you don't have to hard coding the column ID
I know this is a little old now but just in case someone else stumbles across this as I did when looking for an answer to a similar question, I found you can do something like this:
<ItemTemplate>
<asp:ImageButton ID="btnDownload" runat="server"
CommandName="Download"
CommandArgument='<%# Eval("Document_ID") & "," & Eval("Document_Name") %>'
ImageUrl="download.png" ToolTip='<%#"Download " & Eval("Document_Name") %>'
Visible='<%# Not(Eval("Document_ID") = -1) %>' />
</ItemTemplate>
i.e. set the Visible property to evaluate a boolean expression based on your field. If you wanted to display something instead of the download link or button, such as a "Not available" label, then you would just set its Visible property to the opposite boolean expression to your download link. (This is VB.NET not C#, but you get the idea.)
If you're going to be doing this a lot, I suggest writing your own field. The simplest approach is probably to make a NullableHyperlinkField inheriting from HyperlinkField, and render out a plain string if the anchor's URL would otherwise be null.
Use properties on the page to determine if you want to show the label or the link
<asp:GridView ID="gv" runat="server">
<Columns>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:LinkButton runat="server" Visible='<%# ShowLink %>' PostBackUrl="~/Aliases.aspx" >This is the link</asp:LinkButton>
<asp:Label runat="server" Visible='<%# ShowLabel %>'>Aliases label</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The add the properties ShowLink and ShowLable toyour code behind
public bool ShowLabel
{
get
{
//determine if the label should be shown
return false;
}
private set
{
//do nothing
}
}
public bool ShowLink
{
get
{
//determine if the link should be shown
return true;
}
private set
{
//do nothing
}
}

Resources