I am creating dynamically an array, adding a line for each entry of some data. Each entry must have a button to do some stuff with it, but I am stuck at this point. I have this code to create the ASP.NET button:
<asp:Button ID="buttonyes" class="buttonyes" CommandArgument='<%= request.ID %>'
CommandName="AcceptRequest" OnClick='<%= ButtonPressed %>' runat="server"/>
But when I run it, I have multiple errors saying that:
The %= and < or > expressions are not valid.
When I click on the button, I want to call a function written in the index.aspx.cs file linked with my index.aspx, here is ButtonPressed function and with a filter in this function, it choose what action it should do:
protected void ButtonPressed(Object sender, CommandEventArgs e)
{
Button btn = (Button)sender;
switch (btn.CommandName)
{
case "AcceptRequest":
AcceptRequest(btn.CommandArgument.ToString());
break;
case "RefuseRequest":
RefuseRequest(btn.CommandArgument.ToString());
break;
}
}
The problem is that I don't succeed in passing those C# variables as a CommandArgument and CommandName.
I already tried those syntaxes, following some previous questions:
CommandArgument="<%: request.ID %>"
CommandArgument='<%: request.ID %>'
CommandArgument="<%= request.ID %>"
CommandArgument='<%= request.ID %>'
But none of them worked.
EDIT 1:
As #grek40 said below, the OnClick value should be replace like the following:
<asp:Button ID="buttonyes" class="buttonyes" CommandArgument='<%= request.ID %>'
CommandName="AcceptRequest" OnCommand="ButtonPressed" runat="server"/>
EDIT 2:
I would like to know how to pass a C# local variable since those button should be added in a foreach loop like so:
foreach (Request request in requests)
{
%>
<tr>
<td><%: request.applicant.Name + " (" + request.applicant.ID + ")" %></td>
<td><%: request.software.Name %></td>
<td><%: request.date %></td>
<td class="actions">
<asp:Button ID="buttonyes" class="buttonyes" CommandName="AcceptRequest" CommandArgument="<# request.Id %>" OnCommand="ButtonPressed" runat="server"/>
<asp:Button ID="buttonno" class="buttonno" CommandName="RefuseRequest" CommandArgument="<# request.Id %>" OnCommand="ButtonPressed" runat="server"/>
</td>
</tr>
<%
}
By the way, the code above doesn't work, since, as #Nino said, this only works for global variables.
Why not save yourself a whole lot of trouble and switch to a Strongly Typed Repeater Control. You can make it type safe with the ItemType property. The value must the the complete namespace to the class request
Then you will still be able to access the properties like you have now. But instead of using request, you use the fixed name of Item.
<table border="1">
<asp:Repeater ID="Repeater1" runat="server" ItemType="Namespace1.Default1.request">
<ItemTemplate>
<tr>
<td><%# Item.applicant.Name + " (" + Item.applicant.ID + ")" %></td>
<td><%# Item.software.Name %></td>
<td><%# Item.date.ToLongDateString() %></td>
<td class="actions">
<asp:Button ID="buttonyes" class="buttonyes" CommandName="AcceptRequest" CommandArgument='<%# Item.Id %>' OnCommand="ButtonPressed" runat="server" />
<asp:Button ID="buttonno" class="buttonno" CommandName="RefuseRequest" CommandArgument='<%# Item.Id %>' OnCommand="ButtonPressed" runat="server" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
Now you can use the normal way of databinding: CommandArgument='<%# Item.Id %>'
Below the full code for testing...
public List<request> requests = new List<request>();
protected void Page_Load(object sender, EventArgs e)
{
//create some dummy data
for (int i = 0; i < 10; i++)
{
request r = new request() { Id = i, date = DateTime.Now };
r.applicant = new applicant() { Name = "Applicant " + i, ID = 1 + 100 };
r.software = new software() { Name = "Software " + i };
requests.Add(r);
}
if (!Page.IsPostBack)
{
Repeater1.DataSource = requests;
Repeater1.DataBind();
}
}
public class request
{
public int Id { get; set; }
public DateTime date { get; set; }
public applicant applicant { get; set; }
public software software { get; set; }
}
public class applicant
{
public int ID { get; set; }
public string Name { get; set; }
}
public class software
{
public int ID { get; set; }
public string Name { get; set; }
}
you can do it like this:
CommandArgument='<%# request.ID %>'
That way CommandArgument will be assigned during DataBidning phase.
I think you have the command action incorrect.
Most people might think OnClick(), but your method signature is associated with OnCommand()
Change from
OnClick='<%= ButtonPressed %>'
to
OnCommand='<%= ButtonPressed %>'
The OnClick signature is ( object sender, EventArgs e )... OnCommand signature is ( object sender, CommandEventArgs e)... and the expected parameter value should be good.
As for the "OnClick" or "OnCommand", that should be fixed based on the function that will handle the call, such as your "ButtonPressed" method. You do NOT need your "%" wrappers as the function is not changing... your COMMAND NAME can change, but not the method that handles the event...
OnClick='ButtonPressed'
Related
Please consider this scenario:
I have a simple page and I want to log all controls causing postback. I create this simple page. It contains a grid to show some URLs and when user click on an icon a new tab should open:
<form id="form1" runat="server">
<div>
<table style="width: 100%;">
<tr>
<td style="background-color: #b7ffbb; text-align: center;" colspan="2">
<asp:Button ID="Button3" runat="server" Text="Click Me First" Height="55px" OnClick="Button3_Click" />
</td>
</tr>
<tr>
<td style="background-color: #f1d8fe; text-align: center;" colspan="2">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" BackColor="White" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundField DataField="SiteAddress" HeaderText="Address" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="ImageButton1" ImageUrl="~/download.png" runat="server" CommandArgument='<%# Eval("SiteAddress") %>' CommandName="GoTo" Height="32px" Width="32px" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
</table>
</div>
</form>
and code behind:
public partial class WebForm2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button3_Click(object sender, EventArgs e)
{
List<Address> Addresses = new List<Address>()
{
new Address(){ SiteAddress = "https://google.com" },
new Address(){ SiteAddress = "https://yahoo.com" },
new Address(){ SiteAddress = "https://stackoverflow.com" },
new Address(){ SiteAddress = "https://learn.microsoft.com/}" }
};
GridView1.DataSource = Addresses;
GridView1.DataBind();
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "MyScript", "window.open('" + e.CommandArgument.ToString() + "', '_blank')", true);
}
}
class Address
{
public string SiteAddress { get; set; }
}
every thing is fine till here. Now I create a base class for all of my pages and add below codes for finding postback control:
public class MyPageBaseClass : Page
{
protected override void OnInit(EventArgs e)
{
if (!IsPostBack)
{
}
else
{
var ControlId = GetPostBackControlName(); <------
//Log ControlId
}
base.OnInit(e);
}
private string GetPostBackControlName()
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = Page.FindControl(ctrlname);
}
else
{
foreach (string ctl in Page.Request.Form)
{
Control c;
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
string ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = Page.FindControl(ctrlStr);
}
else
{
c = Page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
if (control != null)
return control.ID;
else
return string.Empty;
}
}
and change this line:
public partial class WebForm2 : MyPageBaseClass
Now when I click on icons grid view disappears...(STRANGE...) and nothing happened. When I comment specified line then every thing will be fine...(STRANGE...).
In GetPostBackControlName nothings changed to Request but I don't know why this happened. I checked and I see if I haven't RegisterStartupScript in click event every thing is fine. Please help we to solve this problem.
Thanks
when I click on icons grid view disappears...
ASP.Net page class object instances only live long enough to serve one HTTP request, and each HTTP request rebuilds the entire page by default.
Every time you do a postback, you have a new HTTP request and therefore a new page class object instance and a completely new HTML DOM in the browser. Any work you've done for a previous instance of the page class — such as bind a list of addresses to a grid — no longer exists.
You could fix this by also rebuilding your grid code on each postback, but what I'd really do is skip the whole "RegisterStartupScript" mess and instead make the grid links open the window directly, without a postback at all.
The problem is related to OnInit event. I replaced it with OnPreLoad and every things is fine now.
For search engines: OnInit event has conflict with RegisterStartupScript
I have written a code to fetch news from a website.
The code includes UI page in which i am inserting name of website (from which data to be fetched) & on button click event it fetches the news.
The code is as follows :
<form runat="server" style="margin-left:10px;">
<br /><br />
<asp:TextBox ID="txtSiteName" runat="server"></asp:TextBox> <asp:Button ID="btnSubmit" runat="server" Text="Get News" OnClick="btnSubmit_Click"/><br /><br /><br />
<h3>Here are the latest news</h3><br />
<div style="max-height: 350px; overflow: auto">
<asp:GridView ID="gvRss" runat="server" AutoGenerateColumns="false" ShowHeader="false" Width="90%">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<table width="100%" border="0" cellpadding="0" cellspacing="5">
<tr>
<td>
<asp:CheckBox ID="cbxAddNews" runat="server" />
</td>
<td>
<h3 style="color: #3E7CFF"><%#Eval("Title") %></h3>
</td>
<td width="200px">
<%#Eval("PublishDate") %>
</td>
</tr>
<tr>
<td colspan="2">
<hr />
<%#Eval("Description") %>
</td>
</tr>
<tr>
<td> </td>
<td align="right">
Read More...
</td>
</tr>
</table>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
The codebehind is as follows :
public class Feeds
{
public string Title { get; set; }
public string Link { get; set; }
public string PublishDate { get; set; }
public string Description { get; set; }
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
PopulateRssFeed();
}
private void PopulateRssFeed()
{
//string RssFeedUrl = "https://realty.economictimes.indiatimes.com/rss/topstories";
string RssFeedUrl = txtSiteName.Text;
List<Feeds> feeds = new List<Feeds>();
try
{
XDocument xDoc = new XDocument();
xDoc = XDocument.Load(RssFeedUrl);
var items = (from x in xDoc.Descendants("item")
select new
{
title = x.Element("title").Value,
link = x.Element("link").Value,
pubDate = x.Element("pubDate").Value,
description = x.Element("description").Value
});
if (items != null)
{
foreach (var i in items)
{
Feeds f = new Feeds
{
Title = i.title,
Link = i.link,
PublishDate = i.pubDate,
Description = i.description
};
feeds.Add(f);
}
}
gvRss.DataSource = feeds;
gvRss.DataBind();
}
catch (Exception ex)
{
throw;
}
}
what it does is it takes all the news from one particular website on button click event.
But i want to implement the same functionality using the scheduler! (want to eliminate button click event instead!)
Since i haven't worked on scheduler before, can anyone help me out or any suggestions as how to fetch the data (news) from multiple websites using scheduler & store it in database table instead of directly displaying them??
At client side use setInterval(expression, timeout);.
1) Create a WebMethod at you webpage.
[WebMethod]
public static void UpdateNews()
{
PopulateRssFeed();
}
2) Create a method at client side so that use Ajax to call that WebMethod.
var updateNews = function(){ $.ajax({ type: "POST", url:"YourWebpage.aspx/UpdateNews", contentType: "application/json; charset=utf-8" });}
3) Use SetInterval and call your client side ajax method
setInterval(updateNews(), 5000);//every 5 second
No matter what combination I try, the button (ibtnDeleteDiaryEntry) simply will not raise an event although it does seem to do postback as it should. ViewState is turned on by default, read elsewhere that it is sometimes problematic. Also, I've used the Repeater's OnItemCommand property as required. Any kind of help is appreciated.
EDIT: It seems that the problem is somehow connected to the jQuery UI's Accordion Widget. The repeater is located within a div that is used to initialize the accordion. If I remove the div tags surrounding the repeater, the OnItemCommand event gets called. Very weird.
Markup:
<asp:Repeater ID="repAccordion" OnItemCommand="repAccordion_OnItemCommand" runat="server">
<ItemTemplate>
<h3> <%# "Date: " + Eval("date", "{0:d}") %>
<span class="deleteButtonContainer">
<asp:ImageButton ID="ibtnDeleteDiaryEntry" CommandArgument='<%# Eval("diary_entry_id") %>' CommandName="Delete" AlternateText="ibtnDeleteDiaryEntry" ImageUrl="images/remove_item.png" runat="server" />
</span>
</h3>
<div>
<table>
<tr>
<td>
<asp:Label ID="lblText" runat="server" ForeColor="#AA0114" Text="Text:"></asp:Label>
</td>
</tr>
<tr>
<td>
<%# Eval("text") %>
</td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
Code-behind:
protected void Page_Load(object sender, EventArgs e)
{
_db = new PersonalOrganizerDBEntities();
_diary_entryService = new Diary_EntryService();
_userService = new UserService();
if (!IsPostBack)
{
LoadItems();
}
}
public void LoadItems()
{
long currentUserId = (long) Session["userId"];
User currentUser = _userService.GetById(currentUserId);
Diary_Entry[] diaryEntriesArray =
_diary_entryService.GetAll().Where(current => current.diary_id == currentUser.user_id).ToArray();
if (diaryEntriesArray.Length == 0)
{
noItems.Text = "You currently have no diary entries.";
noItems.Visible = true;
}
else
{
noItems.Visible = false;
}
repAccordion.DataSource = diaryEntriesArray;
repAccordion.DataBind();
}
protected void repAccordion_OnItemCommand(object sender, RepeaterCommandEventArgs e)
{
Response.Write("test");
}
If it doesn't work I would recommend removing OnItemCommand from repeater and adding OnClick event for ImageButton instead. In OnClick event in code behind you can cast 'sender' to ImageButton and read CommandArgument value to get diary_entry_id.
I have this repeater on my page..Under the default column what I want is that there
should be an IF condition that checks my table's "IsDEfault" field value.
If IsDefault=True then the lable below "label1" ie "Yes" should be
displayed inside the repeater else "Make DEfault" link should be displayed..
Now how do I include this IF statement as inline code in my repeater to accomplish what I want ?
<asp:LinkButton ID="lnk1" Text="Make Default" CommandName="SetDefault" runat="server" Visible="True" CommandArgument='<%#Eval("UserID") %>' CausesValidation="false"></asp:LinkButton>
<asp:Label ID="label1" Text="Yes" runat="server" Visible="False"></asp:Label>
I have an idea :-
<%# If DataBinder.Eval(Container.DataItem,"IsDefault") = "True"
Then%>
<%End If%>
How should I form the "Then" statement now?
Please help me with the proper syntax..thnx
Do I need to like make a method that checks if "IsDefault" is true or not and then call it inside of inline code in my repeater ? How do I go about it ?
[EDIT]
I tried as follows:-
<% If (Eval("Container.DataItem,"IsDefault"")="True"?
("<asp:LinkButton ID="lnk1" Text="Set as Default" CommandName="SetDefault1" runat="server" CommandArgument='<%#Eval("User1ID") %>'
CausesValidation="false" Visible=true></asp:LinkButton>") : ("<asp:Label ID="label1" Text="Yes" runat="server" Visible=true></asp:Label>")
)%>
didnt work :( Help!!
If you want some control to be visible only on some condition, set the Visible property according to that condition:
<asp:Label ID="label1" Text="Yes" runat="server"
Visible="<%# DataBinder.Eval(Container.DataItem,"IsDefault") %>" />
EDIT
If you want the control INvisible for the "IsDefault" situation, reverse the test with something like Visible="<%# DataBinder.Eval(Container.DataItem,"IsDefault")==False %>".
I'm not quite sure about the exact syntax, but you should get the idea.
Here's your repeater markup. Notice both controls are hidden at the start:
<asp:Repeater runat="server" ID="rpt1" OnItemDataBound="rpt1_ItemDataBound" onitemcommand="rpt1_ItemCommand">
<ItemTemplate>
<p>
ID: <%# Eval("Id") %>
IsDefault: <%# Eval("IsDefault") %>
Name: <%# Eval("Name") %>
<asp:Label BackColor="Blue" ForeColor="White" runat="server" ID="lDefault" Text="DEFAULT" Visible="false" />
<asp:Button runat="server" ID="btnMakeDefault" Text="Make Default" Visible="false" CommandArgument='<%# Eval("Id") %>' />
</p>
</ItemTemplate>
</asp:Repeater>
And some code to go with it. Note I've simulated the retrieval of your collection of blluser objects, so there is some additional code there relating to this which you won't require as, presumably the bllusers collection that you bind to is coming from a db or something?
Anyway I think this is what you're looking for, but let me know if its not ;-)
//Dummy object for illustrative purposes only.
[Serializable]
public class bllUsers
{
public int Id { get; set; }
public bool isDefault { get; set; }
public string Name { get; set; }
public bllUsers(int _id, bool _isDefault, string _name)
{
this.Id = _id;
this.isDefault = _isDefault;
this.Name = _name;
}
}
protected List<bllUsers> lstUsers{
get
{
if (ViewState["lstUsers"] == null){
ViewState["lstUsers"] = buildUserList();
}
return (List<bllUsers>)ViewState["lstUsers"];
}
set{
ViewState["lstUsers"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
buildGui();
}
}
private List<bllUsers> buildUserList(){
lstUsers = new List<bllUsers>();
lstUsers.Add(new bllUsers(1, false, "Joe Bloggs"));
lstUsers.Add(new bllUsers(2, true, "Charlie Brown"));
lstUsers.Add(new bllUsers(3, true, "Barack Obama"));
return lstUsers;
}
private void buildGui()
{
rpt1.DataSource = lstUsers;
rpt1.DataBind();
}
protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
bllUsers obj = (bllUsers)e.Item.DataItem;//this is the actual bllUser the row is being bound to.
//Set the labels
((Label)e.Item.FindControl("ldefault")).Visible = obj.isDefault;
((Button)e.Item.FindControl("btnMakeDefault")).Visible = ! obj.isDefault;
//Or use a more readable if/else if you want:
if (obj.isDefault)
{
//show/hide
}
else
{
//set visible/invisible
}
}
}
Hope this helps :-)
Sorry to say you to be honest i was unable to understand what actually you wanted to do
If your looking to use the condition in the Item Templet then i think
the following systax will help you
<asp:LinkButton ID="Label1" runat="server"
Text='<%# ((Eval("Cond"))="True" ? Eval("Result for True") : Eval("Result for False") )%>'></asp:LinkButton>
For the solution, I cannot use any postback methods, because this is all working through ajax. The solution need to be implemented in the asp.net code.
I have a List<WebPage> that contains a list of Links (List<Link>) and I need for all the links to bind repetitive information such as page title, id, url. Here is my current repeater.
<div id="result">
<asp:Repeater runat="server" id="results">
<Itemtemplate>
<asp:Repeater runat="server" datasource='<%# Eval("Links") %>'>
<Itemtemplate>
<tr class="gradeX odd">
<td><%# Eval("Id") %></td> //property of WebPage (part of results repeater)
<td><%# Eval("Title") %></td> //property of WebPage (part of results repeater)
<td><%# Eval("Url") %></td> //property of WebPage (part of results repeater)
<td><%# Eval("URL") %></td>//Property of Link
<td><%# Eval("URLType") %></td> //Property of Link
<td><%# Eval("URLState") %></td> //Property of Link
</tr>
</Itemtemplate>
</asp:Repeater>
</Itemtemplate>
</asp:Repeater>
</div>
of course this doesnt work, how can i do this?
Thanks for your help!
I'm assuming the problem you're trying to solve here is how to include properties from multiple levels in a nested object-- some properties from the top level but other properties from the lower level. One easy way to do this is to transform the inner collection into a new type which contains a mix of all the properties you need.
Here's a code sample illustrating this technique using IEnumerable.Select and C# Anonymous Classes to create a new class:
<%# Page Title="Home Page" Language="C#" %>
<div id="result">
<asp:Repeater runat="server" id="results">
<ItemTemplate>
<asp:Repeater runat="server" datasource='<%# ((WebPage)Container.DataItem).Links.Select ( link => new {
Id = ((WebPage)Container.DataItem).Id,
Title = ((WebPage)Container.DataItem).Title,
Url = ((WebPage)Container.DataItem).Url,
URL = link.URL,
URLType = link.URLType,
URLState = link.URLState
}) %>'>
<ItemTemplate>
<tr class="gradeX odd">
<td><%# Eval("Id") %></td> <!--property of WebPage (part of results repeater) -->
<td><%# Eval("Title") %></td> <!--property of WebPage (part of results repeater) -->
<td><%# Eval("Url") %></td> <!--property of WebPage (part of results repeater) -->
<td><%# Eval("URL") %></td><!--Property of Link -->
<td><%# Eval("URLType") %></td> <!--Property of Link-->
<td><%# Eval("URLState") %></td> <!--Property of Link -->
</tr>
</ItemTemplate>
</asp:Repeater>
</Itemtemplate>
</asp:Repeater>
</div>
<script runat="server">
public class Link
{
public string URL { get; set; }
public int URLType { get; set; }
public int URLState { get; set; }
}
public class WebPage
{
public string Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public List<Link> Links { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
WebPage[] pages = new WebPage[]
{
new WebPage { Id = "foo",
Title = "foobar",
Url = "http://foo.bar",
Links = new List<Link> ( new Link[] {
new Link {URL = "http://something", URLType = 1, URLState = 2},
new Link {URL = "http://someotherthing", URLType = 3, URLState = 4}
})
},
new WebPage { Id = "excellent",
Title = "excellent Title",
Url = "http://excellent.com",
Links = new List<Link> ( new Link[] {
new Link {URL = "http://excellent", URLType = 5, URLState = 6},
new Link {URL = "http://totallyexcellent", URLType = 7, URLState = 8}
})
}
};
results.DataSource = pages;
results.DataBind();
}
</script>