Hide EmptyDataTemplate but leave header visible - asp.net

I have an EmptyDataTemplate on my ASP.NET webform which allows users to add a record to the database. Depending on the permissions of the user, this EmptyDataTemplate needs to be visible and hidden if no data is found (I have this working!)
For example, my user has Read Access only. When they search a specific criteria, no results are displayed they cannot see the EmptyDataTemplate. However, if they search a criteria, and there is data, data is displayed WITHOUT the headers.
Can someone please help explain why this is happening and if there's a way around it?
The headers are HeaderText on TemplateFields.
I'm hoping it's a general trick.
Thank you in advance for your help!
Please note, it's the HeaderText in the TemplateFields I want to display- not the in the emptyDataTemplate as they'll head up the columns of data that match the search criteria.
edit: code added as requested
For hiding the EmptyDataTemplate:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
Control control = null;
control = GridView1.Controls[0].Controls[0];
if (userManagement.getMIFReadWriteAccess() == "Read")
{
control.Visible = false;
Export_All.Visible = true;
}
else if (userManagement.getMIFReadWriteAccess() == "Write")
{
control.Visible = true;
Export_All.Visible = true;
}
}
in markup for the header text (i've only shown one column but the markup is the same for all of them)
<asp:TemplateField HeaderText="ID">
<ItemTemplate>
<asp:Label ID="lbl_Index" runat="server" Text='<%#Eval("id") %>'></asp:Label>
<asp:Label ID="lbl_ID" runat="server" Text="" Visible="false"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
EmptyDataTemplate:
<EmptyDataTemplate>
<div id="emptyData" runat="server">
<tr>
<th></th>
<th>Serial Number</th>
<th>Comments</th>
<th>Review Date</th>
<th>Approved By</th>
</tr>
<tr>
<td>
<asp:Button runat="server" ID="btInsert" Text="In" OnClick="Add" CommandName="EmptyDataTemplate" Class="Button" OnClientClick="return confirm('You are about to confirm this action. Please confirm this action by clicking OK. If you do not wish to do this, please select Cancel.');" />
<br />
<asp:Button runat="server" ID="btInsertOut" Text="Out" OnClick="AddOut" CommandName="EmptyDataTemplate" Class="Button" OnClientClick="return confirm('You are about to confirm this action. Please confirm this action by clicking OK. If you do not wish to do this, please select Cancel.');" />
</td>
<td>
<asp:TextBox runat="server" ID="tb_Serial_Number" CssClass="text"></asp:TextBox>
</td>
<td>
<asp:TextBox ID="tb_comments" Width="100%" MaxLength="50" runat="server" placeholder="max 50 characters"/>
</td>
<td>
<asp:TextBox ID="tb_reviewDate" runat="server" DataFormatString="{0:dd/mm/yyyy}" Text='<%#Eval("review_by") %>'></asp:TextBox>
</td>
<td><asp:DropDownList ID="tb_approved_by" runat="server">
</asp:DropDownList> </td>
</tr>
</div>
</EmptyDataTemplate>

After trial and error, I found that programatically adding a header row in C# did the trick. Probably not the best way of doing it, but it worked.
Code is as follows:
#region show the emptyDataTemplate depending on user rights
Control control = null;
control = GridView1.Controls[0].Controls[0];
if (userManagement.getMIFReadWriteAccess() == "Read")
{
control.Visible = false;
GridViewRow HeaderRow = new GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Insert);
TableCell HeaderCell2 = new TableCell();
HeaderCell2.Text = "Country";
HeaderCell2.ColumnSpan = 1;
HeaderRow.Cells.Add(HeaderCell2);
//Repeat the above for every column of data you have!
GridView1.Controls[0].Controls.AddAt(0, HeaderRow);

Related

ListView with Dynamic Controls updating all rows as contents of last row

I have a page which displays data from multiple tables in a one-to-many relationship via various FormViews and ListViews. A ListView is nested within a FormView and the correct data displays but, when I go to update, the last record in the ListView updates all rows within the ListView with its contents and I can't figure out why.
Here is some of the code:
<asp:FormView runat="server" ItemType="Table1"
DefaultMode="Edit" DataKeyNames="Table1_key"
SelectMethod="GetAll" OnItemCommand="ItemCommand"
UpdateMethod="UpdateTables" RenderOuterTable="false">
<EmptyDataTemplate>
Cannot find the Episode with Episode key <%: FriendlyUrl.Segments[0] %>
</EmptyDataTemplate>
<EditItemTemplate>
<asp:DynamicControl Mode="Edit" DataField="foo1" runat="server"/>
<asp:Button runat="server" ID="UpdateButton" CommandName="Update" Text="Update" CssClass="btn btn-primary" />
</EditItemTemplate>
<asp:ListView ID="ListView1" runat="server"
DataKeyNames="Table2_key" SelectMethod="GetTable2"
ItemType="Table2">
<ItemTemplate>
<tr>
<td>
//this doesn't update properly
<asp:DynamicControl runat="server" DataField="foo" ID="foo" Mode="Edit" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
</asp:FormView>
Update method in code-behind (which works for updating the FormView (i.e. Table1) but not the ListView content (Table2):
public void UpdateTables(int Table1_key)
{
using (_db)
{
var item = _db.Table1.Find(Table1_key);
if (item == null)
{
// The item wasn't found
ModelState.AddModelError("", String.Format("Item with id {0} was not found", Table1_key));
return;
}
TryUpdateModel(item); // this updates the foo1 property
if (ModelState.IsValid)
{
_db.SaveChanges();
}
var lesions = _db.Table2.Where(cl => cl.Table1_key == Table1_key);
foreach (var lesion in lesions)
{
TryUpdateModel(lesion); //this updates ALL the children with the value I put in the last textbox.
}
_db.SaveChanges();
}
}
I can't find anything to sort this but surely someone has wanted to do the same as me, i.e. display data from multiple tables but only have one update button for everything? Thanks!

How can I retrieve the value of a control within an ASP.Net Dynamic Data Custom Field Template?

Long story short, for an old project I used ASP.Net Dynamic Data and probably did a terrible job with it. One of the Field Templates has multiple controls in it, and now I need to get at the value of one control from the FormView's Submit event because we changed the way that value is stored.
I can find the Field Template itself using FindFieldTemplate... but I can't figure out how to get to the controls inside of the template.
How can I do that without re-engineering the whole thing to pull that one field out? It would probably be more correct to re-engineer it, but this is a quick fix for a website that's going to be scrapped in a couple months.
EDIT: Was asked to show code so here it is. The FormView is pretty standard, just uses an . The Field Template actually has it's own listview and I'm controlling it's mode in codebehind. But I need to get the value of txtTitle.
Ticket_TicketMemo.ascx:
<asp:ListView ID="lvTicketMemos" DataSourceID="ldsTicketMemo"
InsertItemPosition="FirstItem" OnLoad="lvTicketMemo_Load" runat="server">
<LayoutTemplate>
<div style="overflow:auto; height:125px; width:600px;">
<table class="ListViewTable" runat="server">
<tr id="itemPlaceHolder" runat="server" />
</table>
</div>
</LayoutTemplate>
<ItemTemplate>
<tr valign="top" class='<%# Container.DataItemIndex % 2 == 0 ? "" : "Alternate" %>'>
<td><asp:DynamicControl ID="dcType" DataField="Type" runat="server" /></td>
<td><asp:DynamicControl ID="dcMemo" DataField="Memo" runat="server" /></td>
<td><asp:DynamicControl ID="dcCreateTime" DataField="CreateTime" runat="server" /></td>
</tr>
</ItemTemplate>
<InsertItemTemplate>
<tr valign="top">
<td colspan="3">
<asp:TextBox ID="txtTitle" Width="99%" Visible="false" OnLoad="txtTitle_Load" runat="server" /><br /><br />
</td>
</tr>
<tr valign="top">
<td colspan="3" width="600px">
<asp:TextBox ID="txtMemo" Text='<%# Bind("Memo") %>' Width="99%" OnLoad="txtMemo_Load" TextMode="MultiLine"
Rows="5" runat="server" />
<asp:RequiredFieldValidator ID="rfvMemo" Text="Must enter notes" ControlToValidate="txtMemo" runat="server" />
</td>
</tr>
</InsertItemTemplate>
I have just simulated your problem in my Dynamic Data project. Based on my research (and search) in order to get control value (not from DynamicControl value) in Dynamic Data you should implement the following method (i am using this method in my project and i have found one on Steve blog, i don't remember full link):
/// <summary>
/// Get the control by searching recursively for it.
/// </summary>
/// <param name="Root">The control to start the search at.</param>
/// <param name="Id">The ID of the control to find</param>
/// <returns>The control the was found or NULL if not found</returns>
public static Control FindControlRecursive(this Control Root, string Id)
{
if (Root.ClientID.IndexOf(Id) > 0)
return Root;
foreach (Control Ctl in Root.Controls)
{
Control FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
Now, my EXAMPLE.
First, my custom Insert.aspx page with FormView and EntityDataSource:
<asp:FormView runat="server" ID="FormView1" DataSourceID="DetailsDataSource" DefaultMode="Insert"
OnItemCommand="FormView1_ItemCommand" RenderOuterTable="false">
<InsertItemTemplate>
<table>
<tr valign="top">
<td colspan="3">
<asp:TextBox ID="txtTitle" Width="99%" Visible="true" runat="server" /><br />
<br />
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
<asp:EntityDataSource ID="DetailsDataSource" runat="server" EnableInsert="true" OnInserted="DetailsDataSource_Inserted" />
Then, Inserted event of EntityDataSource:
protected MetaTable table;
protected void DetailsDataSource_Inserted(object sender, EntityDataSourceChangedEventArgs e)
{
if (e.Exception == null || e.ExceptionHandled)
{
string strTitle = String.Empty;
Control CtlTitle = FormView1.FindControlRecursive("txtTitle");
if (CtlTitle != null)
{
TextBox TextBoxTitle = (TextBox)CtlTitle;
strTitle = TextBoxTitle.Text;
}
Response.Redirect(table.ListActionPath + "?" + "Department_Id=" + strTitle);
}
}
Finally, i enter the text into txtTitle, for example, 13 and then i get

How to get Selected Value in FormView Control?

I'm working with an application develop by ASP.NET, the problem I face is using FormView control, the FormView Control has ItemTemplate, InsertItemTemplate and EditItemTemplate.
Below is the code fragment of InsertItemTemplate:
<asp:FormView ID="FormView1" runat="server" DefaultMode="ReadOnly">
<InsertItemTemplate>
<table cellpadding="0" cellspacing="0">
<tr>
<td>
<asp:Label id="lblPS" runat="server" Text="Process Status"></asp:Label>
</td>
<td>
<asp:DropDownList ID="ddlPS" runat="server"></asp:DropDownList>
</td>
</tr>
<tr>
<td>
<asp:Label id="lblAP" runat="server" Text="Action Plan"></asp:Label>
</td>
<td>
<asp:TextBox id="txtAP" runat="server" Width="230px" TextMode="MultiLine" Rows="5"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" />
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
In Page_Load event, I do DataSource Binding into the DropDownList as below:
FormView1.ChangeMode(FormViewMode.Insert);
DropDownList ddlPS = FormView1.FindControl("ddlPS") as DropDownList;
ddlPS.DataSource=GetProcessStatus();
ddlPS.DataBind();
ddlPS.Items.Insert(0, new System.Web.UI.WebControls.ListItem("- Please Select -", "- Please Select -"));
The data binding into DropDownList and the "- Please Select -" was ok.
Here the problem comes, when Submit Button click, I wanted to get user selected DropDownList Value, but the DropDownList.SelectedItem.Text always return me "- Please Select -".
Please advise how can I get the user selected value in InsertItemTemplate.
The problem is with your DataBind on Page Load event.
When you DataBind you clear the existing values and hence loose the selected value.
A drop down list remembers the items in it, so you don't need to DataBind on every postback.
Your could should be like this.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
DropDownList ddlPS = FormView1.FindControl("ddlPS") as DropDownList;
ddlPS.DataSource=GetProcessStatus();
ddlPS.DataBind();
ddlPS.Items.Insert(0, new System.Web.UI.WebControls.ListItem("- Please Select -", "- Please Select -"));
}
}

Render empty repeater

When Repeater contains no items it's not get rendered in HTML at all, even HeaderTemplate or FooterTemplate. I need to manipulate it on client-side even if it's empty.
Is there any way to always render Repeater in HTML?
In the <FooterTemplate>, add a Label with some empty data text and set its visible property to false.
<FooterTemplate>
<table>
<tr>
<td>
<asp:Label ID="lblEmptyData"
Text="No Data To Display" runat="server" Visible="false">
</asp:Label>
</td>
</tr>
</table>
</FooterTemplate>
Now check the the data while binding repeater, if no rows return then make label visible otherwise no action.
More details here.
as #Saurabh said, use <FooterTemplate> add a Label with specifying your message in the Text property and set its visible property to false like this:
<FooterTemplate>
<%-- Label used for showing Error Message --%>
<asp:Label ID="ErrorMessage" runat="server" Text="Sorry!!" Visible="false">
</asp:Label>
</FooterTemplate>
Then in the code-behind use the following logic; if there is no data, show the message, otherwise, show the data as following:
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Repeater rpt = sender as Repeater; // Get the Repeater control object.
// If the Repeater contains no data.
if (rpt != null && rpt.Items.Count < 1)
{
if (e.Item.ItemType == ListItemType.Footer)
{
// Show the Error Label (if no data is present).
Label ErrorMessage = e.Item.FindControl("ErrorMessage") as Label;
if (ErrorMessage != null)
{
ErrorMessage.Visible = true;
}
}
}
}
<asp:Repeater ID="rptList" runat="server" DataSourceID="odsList">
...
<FooterTemplate>
<%if (rptList.Items.Count == 0)
{ %>
**Your message**
<%} %>
</FooterTemplate>
</asp:Repeater>
Try this
protected bool IsDataEmpty
{
get
{
ICollection list = Repeater1.DataSource as ICollection;
return list.Count == 0 ? true : false;
}
}
In Markup :
<table width="80%">
<tr runat="server"
visible='<%# IsDataEmpty %>'>
<td>
There is no data to display
</td>
</tr>
for step by step follow the link :Link

how to update label value of gridview with another value

I have gridview with ajax rating control where i am updating rating value on change event and i am saving that data into the database using sql datasource and i want to show that change value into another label .But when i am updating the value it makes change in database but not in the label. please tell me how can i change lbel value at that same time i am using these code.
<asp:GridView ID="GVTweet" runat="server" AllowSorting="True" DataKeyNames="id" AllowPaging="true"
AutoGenerateColumns="False" GridLines="Horizontal" PageSize="15" Width="700px"
onselectedindexchanged="GVTweet_SelectedIndexChanged"
onrowcancelingedit="GVTweet_RowCancelingEdit"
onrowediting="GVTweet_RowEditing"
onrowupdated="GVTweet_RowUpdated" onrowupdating="GVTweet_RowUpdating"
DataSourceID="SqlDataSource2"
onpageindexchanging="GVTweet_PageIndexChanging" >
<HeaderStyle />
<Columns>
<asp:TemplateField HeaderImageUrl="~/images/rate1.png"
HeaderStyle-CssClass="headerCss1" HeaderText="Rate(1-5)"
SortExpression="Rating" >
<ItemTemplate>
<table border="0" cellpadding="0" cellspacing="0" width="auto">
<tr style="width:150px;" valign="top" >
<td style="height:30px;">
<asp:Label ID="lblTotalRate" runat="server"
Text='<%#DataBinder.Eval(Container.DataItem, "TotalRate")%>'></asp:Label>
</td>
</tr>
<tr style="width:150px;" valign="top" >
<td style="height:30px;">
<asp:UpdatePanel ID="updtpnlTweet" runat="server">
<ContentTemplate>
<cc1:Rating ID="rateTweet" runat="server" CurrentRating='<%# Bind("Rating") %>'
EmptyStarCssClass="empatyStarRating" FilledStarCssClass="filledStarRating"
MaxRating="5" onchanged="rateTweet_Changed" StarCssClass="ratingStar"
WaitingStarCssClass="savedStarRating">
</cc1:Rating>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
</ItemTemplate>
<HeaderStyle CssClass="headerCss1" />
</asp:TemplateField>
this is html that i using and i want that rating value after updation in this label lblTotalRate.
protected void rateTweet_Changed(object sender, AjaxControlToolkit.RatingEventArgs e)
{
try
{
// cast rating control which has initiated the call:
AjaxControlToolkit.Rating myRating = (AjaxControlToolkit.Rating)sender;
// regular expression which will help identifying row number:
System.Text.RegularExpressions.Regex rexLineNo = new System.Text.RegularExpressions.Regex("ctl\\d+");
// update the record based on the recodrd id
this.updateRating(this.ProductId(rexLineNo.Match(myRating.UniqueID).ToString()), e.Value);
// the above line does the following:
// rexLineNo.Match(myRating.UniqueID).ToString() - finds "ctl and line number
//GVTweet.DataSourceID = "SqlDataSource2";
// GVTweet.DataBind();
GVTweet_RowUpdated( sender2, e2);
// this.Page.Form.Action = "AddRating()";
// SqlDataSource2_Updated(sender1, e1);
}
catch
{
}
}
If any buddy has please tell me .javascript and both is ok for me.
This is code behind code
enter code here
Seems that a piece of code is missing...
anyway, as far as I can see from the code, the label is not into an UpdatePanel. If the expected behavior is to change asynchronously both of the controls you have to manage a partial update in the Label too, or trigger a complete page postback (which is not probably what you want).

Resources