Add an additional label control to an <ItemTemplate> dynamically in certain cases - asp.net

How can I add an extra label control dynamically (should be added only on certain conditions).
I am trying to do something like this:
<asp:DataGrid id="dg" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateColumn SortExpression="Column1">
<HeaderTemplate>
<asp:LinkButton Runat="server" text="Column1 Hdr" ID="col1Hdr">
</asp:LinkButton>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="col1Label" runat="server" Text='<%# Method1(DataBinder.Eval(Container.DataItem, "Column1").ToString(), DataBinder.Eval(Container.DataItem, "Column2").ToString()) %>' >
<asp:PlaceHolder ID="col2Holder" runat="server"></asp:PlaceHolder>
</asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
Alternatively, I tried putting the placeholder in a seperate template:
<EditItemTemplate>
<asp:PlaceHolder ID="col2Holder" runat="server"></asp:PlaceHolder>
</EditItemTemplate>
but to no avail.
Any tips on how I can create the Placeholder only in some cases (like for some values of Column1/Column2), rather than opt for a repeater approach...
I get a null reference exception but that was solved when I had to explicitly mention:
protected PlaceHolder col2Holder = new Placeholder();
instead of
protected PlaceHolder col2Holder;
But though method1 is able to set the 'Column1's text value correctly, it does nothing for the Column2's value...
Is there something I'm missing or is there a different way to do this?
Here's method1's defn:
public string Method1(string col1, string col2)
{
col1 += "Called method1";
Label col2label= new Label();
col2label.Visible = true;
col2label.Text = col2;
col2Holder.Controls.Add(col2label);
col2Holder.DataBind();
return col1;
}

Where and when do you need the extra control to be inserted?
You should most likely hookup a method to the OnItemDataBound event and in there decide whether to add a control or not. The event gives you a reference to the item being bound so you can say e.Item.Controls.Add(your_control)
Update
Ah, now i get it what you're asking for. You need to add another argument to your Method1 that takes a DataGridItem. When you call Method1 you add it like this Method1(Container) where Container refers to the DataGridItem in question. Then you can say in the Method1
public string Method1(DataGridItem item)
{
string col1 = DataBinder.Eval(item.DataItem, "Column1").ToString();
string col2 = DataBinder.Eval(item.DataItem, "Column2").ToString();
var col2label = new Label() { Visible = true, Text = col2 };
var col2Holder = item.FindControl("col2Holder");
col2Holder.Controls.Add(col2label);
return col1 + "Called method1";
}
Btw, you can't add any controls to a Label, your ItemTemplate should look like this
<ItemTemplate>
<asp:Label ID="col1Label" runat="server" Text="<%# Method1(Container) %>" />
<asp:PlaceHolder ID="col2Holder" runat="server" />
</ItemTemplate>
If you want the new Label to be nested inside the first label, you should do that explicit in the method, and leave out the placeholder:
<ItemTemplate>
<asp:Label ID="label" runat="server" Text="<%# Method1(Container) %>" />
</ItemTemplate>
public string Method1(DataGridItem item)
{
string col1 = DataBinder.Eval(item.DataItem, "Column1").ToString();
string col2 = DataBinder.Eval(item.DataItem, "Column2").ToString();
var label = item.FindControl("label");
var col2label = new Label() { Visible = true, Text = col2 };
col1Holder.Controls.Add(col2label);
return col1 + "Called method1";
}

Related

Hide button in gridview when field is Null

I have a grid view where some of the rows have attached pictures. when I press Button2 I pull information from the sql record, about which folder on the server that has the pictures.
This works already, but I can not get the button to only be visible in the rows that have image folder attached.
I've googled a long time and found different solutions similar to the following, but I can not get it to work.
What am I doing wrong?
<asp:SqlDataSource ID="SqlDSodinRSSfeb" runat="server"
ConnectionString="<%$ ConnectionStrings:herning_brand_dk_dbConnectionString %>"
SelectCommand="SELECT PubDateTime, Melding, Station, PhotoFolder FROM OdinRSS ">
</asp:SqlDataSource>
<asp:GridView ID="GridView14" runat="server" DataSourceID="SqlDSodinRSSfeb"
AutoGenerateColumns="False" Width="500px" OnRowCommand="Button_RowCommand" >
<Columns>
<asp:BoundField DataField="PubDateTime" HeaderText="Tidspunkt" />
<asp:BoundField DataField="Melding" HeaderText="Melding for udkaldet" />
<asp:BoundField DataField="Station" HeaderText="Station" />
<asp:TemplateField HeaderText="Foto" >
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("PhotoFolder") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Button ID="Button2" runat="server" Text="Foto" Visible='<%# Eval("PhotoFolder") != "Null" %>'
CommandName="ButtonClick" CommandArgument='<%# Eval("PhotoFolder") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My .cs
protected void Button_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandArgument != null)
{
switch (e.CommandName)
{
case "ButtonClick":
{
int Folder = Convert.ToInt32(e.CommandArgument);
PhotoList(Folder);
}
break;
}
}
}
void PhotoList(int FolderNumber)
{
var imagePaths = Directory.GetFiles(Server.MapPath("PhotoFolder\\" + FolderNumber));
var imageNames = new string[imagePaths.Length];
for (int i = 0; i < imagePaths.Length; i++)
{
imageNames[i] = imagePaths[i].Substring(imagePaths[i].LastIndexOf("\\") + 1);
}
var dt = new DataTable();
dt.Columns.Add("ImageName", typeof(string));
dt.Columns.Add("ImagePath", typeof(string));
foreach (var imgName in imageNames)
{
DataRow dr = dt.NewRow();
dr["ImageName"] = RemoveExtension(imgName);
dr["ImagePath"] = "PhotoFolder/" + FolderNumber + "/" + imgName;
dt.Rows.Add(dr);
}
DataList1.DataSource = dt;
DataList1.DataBind();
}
string RemoveExtension(string imgName)
{
return imgName
.Replace(".jpg", "")
.Replace(".png", "");
}
The sql field "PhotoFolder" is a nvarchar(50). If there is photos for the record, the field has a number from 100 and up, that refares to the folder containing photos. If there are no photo for the record, the field contains "Null"
I have also tried:
<asp:Button ID="Button2" runat="server" Text="Foto" Visible='<%# Eval("PhotoFolder").ToString() != "Null" %>'
But the button is shown in all rows, not just the ones that has a string(number) in "PhotoFolder"
It can be achieved simple in Inline code
<asp:ImageButton ID="ibtnBranchType1" runat="server" ImageUrl='<%# "~/images/" + Eval("branchtype1")+".png" %>' Visible='<%# Convert.ToString(Eval("branchtype1"))=="" ? false : true %>' Height="20px"/>
Here Eval("branchtype1") we are getting value of id from data table like 1, 2, 3 etc. and our image folder consists images like 1.png, 2.png, 3.png etc.,
Visible='<%# Convert.ToString(Eval("branchtype1"))=="" ? false : true %>'
if value doesn't contain any id it will get null. we will compare it with empty string using ternary operator.
Try this.
Markup
Visible='<%# HideEmptyPhotoFolder(Eval("PhotoFolder")) %>'
Code-Behind
protected bool HideEmptyPhotoFolder(object photoFolder)
{
return photoFolder != null && !String.IsNullOrEmpty(photoFolder.ToString());
}
You can simply do that in GridView RowDataBound event.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowdatabound.aspx
As per your question you should write the code for checking the rows containing the image,
you can write the code in RowDatabound event,and set visible property of button to false on that row which doesn't contain image.

Binding data to Gridview Header Template? In Asp.net

In web application, I am trying to bind the Header Template of the gridivew, but i am not able to bind the data to gridview header.
<asp:GridView ID ="grdInner" runat ="server" AutoGenerateColumns ="false" >
<Columns >
<asp:TemplateField >
<HeaderTemplate >
<asp:Label ID="lblHeader" runat="server" Text='<%# Eval("title") %>'></asp:Label>
</HeaderTemplate>
<ItemTemplate >
<asp:Label ID ="lblDesc" runat ="server" Text ='<%# Eval("description") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Following code achieves the same things
<asp:GridView runat="server" ID="gridView" onrowdatabound="gridView_OnRowDataBound" AutoGenerateColumns="false">
<columns>
<asp:TemplateField>
<HeaderTemplate><asp:Label runat="server" ID="lblHeader"></asp:Label></HeaderTemplate>
</asp:TemplateField>
</columns>
</asp:GridView>
You can set label text in OnRowDataBound event
protected void gridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
((Label)e.Row.FindControl("lblHeader") as Label).Text = "Your Data here";
}
Another way to do this that is fairly simple if you want to bind the DataTable column headers to the Gridview headers (for example, you are generating DataTables where the column names can be different and you want these dynamic names to be the GridView header column names).
DataTable dt = // Call your DataTable here.
// Get your column names here.
string nutrient = dt.Columns[2].ColumnName;
string nutrient1 = dt.Columns[3].ColumnName;
string nutrient2 = dt.Columns[4].ColumnName;
string nutrient3 = dt.Columns[5].ColumnName;
string nutrient4 = dt.Columns[6].ColumnName;
string nutrient5 = dt.Columns[7].ColumnName;
GridView1.DataSource = dt;
GridView1.DataBind();
if (GridView1.Rows.Count > 0)
{
GridView1.HeaderRow.Cells[2].Text = nutrient;
GridView1.HeaderRow.Cells[3].Text = nutrient1;
GridView1.HeaderRow.Cells[4].Text = nutrient2;
GridView1.HeaderRow.Cells[5].Text = nutrient3;
GridView1.HeaderRow.Cells[6].Text = nutrient4;
GridView1.HeaderRow.Cells[7].Text = nutrient5;
}
You can also do the same thing with the footer row using GridView1.FooterRow.Cells[x].Text = ...

calling a function in repeater asp.net

I want to call a function to bind data to Repeater . Do I need to Set dataSource Property of this control or Repeater .DataBind() will work.
<asp:Repeater ID="RepeaterDays" runat="server">
<ItemTemplate>
<ul>
<asp:Label ID="lblDays" runat="server" Text='<%#ChandanIdiot()%>'></asp:Label>
</ul>
</ItemTemplate>
</asp:Repeater>
I have written RepeaterDays.Databind(), but the function is not called.
This is displaying nothing.
Is ChandanIdiot() a protected function that returns a string?
protected string ChandanIdiot() {
return "test";
}
If you want to actually do some data processing, you will have to include a parameter:
protected string ChandanIdiot(object obj) {
return "test " + obj;
}
And, assuming that there is a property called "Name" on the object that you are reapeating, you would have the following:
<asp:Label ID="lblDays" runat="server" Text='<%# ChandanIdiot(Eval("Name")) %>' />
Source:
<asp:TemplateField HeaderText="Unit Price">
<ItemTemplate>
<%# ChandanIdiot( Eval("product_unitprice"))%>
<!--product_unitprice is table colomn name -->
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBox4" runat="server" ></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
C#:
protected string ChandanIdiot(object ob) {
string typ = ob.ToString(); //selected value stored in ob
if (typ == "some function") {
//do somthing
}
return typ ; //value return to <%# ChandanIdiot( Eval("product_unitprice"))%>
}

Select All CheckBoxes in GridView ASP.NET using JQuery

I have checkBoxes in my Gridview templete columns called "Category A" and "Category B".
I want Select-All functionality, i.e. when the user checks the Select-All check Box in category A column, all the checkboxes must get checked under that column. Same for Category B.
I am trying with the code below. The problem with my code is, it selects all the check boxes in the entire gridview, "Category A" as well as "Category B"s checkboxes.
But, I want only checkboxes selected under the same column.
function SelectAllCheckboxesA(chk) {
$('#<%=gvSurveys.ClientID %>').find("input:checkbox").each(function() {
if (this != chk) {
if ($(this).hasClass('CatA') != false) {
this.checked = chk.checked;
}
}
else {
alert($(this));
}
});
}
<asp:GridView ID="gvSurveys" runat="server" AutoGenerateColumns="false" AllowSorting="True" Width="1500px">
<Columns>
<asp:TemplateField>
<HeaderTemplate>Category A
<asp:CheckBox ID="chkSelectAllCatA" runat="server" Visible="false" onclick="javascript:SelectAllCheckboxesA(this);" CssClass="SACatA" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkCatA" runat="server" Enabled="false" CssClass="CatA" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Category B
<asp:CheckBox ID="chkSelectAllCatB" runat="server" Visible="false" CssClass="CatB" onclick="javascript:SelectAllCheckboxesB(this);" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkCatB" runat="server" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
This is based on solution proposed by Ashish Patil with some modifications to clear checkbox in the header row when any of the checkboxes in grid rows is unchecked.
In GridView create a template column:
<asp:templatefield>
<headertemplate>
<asp:CheckBox ID="chkSelectAll" cssclass="chkHeader" runat="server" />
</headertemplate>
<itemtemplate>
<asp:CheckBox ID="chkSelect" cssclass="chkItem" runat="server"/>
</itemtemplate>
</asp:templatefield>
jquery script, put it in $(document).ready for example:
var headerChk = $(".chkHeader input");
var itemChk = $(".chkItem input");
headerChk.click(function () {
itemChk.each(function () {
this.checked = headerChk[0].checked; })
});
itemChk.each(function () {
$(this).click(function () {
if (this.checked == false) { headerChk[0].checked = false; }
})
});
Why don't you select only the Checkboxes of CategoryA:
$('#<%=gvSurveys.ClientID %>').find("input:checkbox[Id*=chkCatA]")
Would that work?
Change the selectAll checkboxes to have the same class. Then extract the class from the checkbox and use it as part of the selector, filtering out the select. This will simplify things a lot since you know that all the matched inputs will simply need to get the checked value from the parameter.
function SelectAllCheckboxesA(chk) {
var $chk = $(chk);
var myClass = $chk.attr('class');
$('#<%=gvSurveys.ClientID %>')
.find("input." + myClass + ":checkbox" )
.not($chk)
.attr('checked', $chk.attr('checked') );
}
$('#<%=gvSurveys.ClientID %>').find('input[Id*="chkCatA"]:checkbox').each(function() {
if (this != chk) {
this.checked = chk.checked;
}
});
Create the row with a checkbox in the header:
<asp:TemplateField HeaderText="Merged Client">
<HeaderTemplate>
<asp:CheckBox ID="chkboxSelectAll" runat="server" AutoPostBack="true" OnCheckedChanged="chkboxSelectAll_CheckedChanged" ></asp:CheckBox> Merged Client
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="CheckMergedClient" **runat="server"** **onclick="CheckChanged()" OnCheckedChanged="CheckMergedClient_CheckedChanged"** **AutoPostBack="true"** value='<%# Eval("ClientId") %>'/> </ItemTemplate>
</asp:TemplateField>
In code behind add the OnCheckChanged event handler to select or deselect all :
protected void chkboxSelectAll_CheckedChanged(object sender, EventArgs e)
{
CheckBox ChkBoxHeader = (CheckBox)ClientMatchGridView.HeaderRow.FindControl("chkboxSelectAll");
foreach (GridViewRow row in ClientMatchGridView.Rows)
{
CheckBox ChkBoxRows = (CheckBox)row.FindControl("CheckMergedClient");
if (ChkBoxHeader.Checked == true)
{
ChkBoxRows.Checked = true;
}
else
{
ChkBoxRows.Checked = false;
}
}
}

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
}
}

Categories

Resources