I get this error:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name:index.
Same code was running perfectly in windows form app, but in asp.net i see this error.
My code is here:
public partial class Timeline : System.Web.UI.Page
{
TwitterService servis;
ListBox tweetid = new ListBox();
protected void Page_Load(object sender, EventArgs e)
{
servis = new TwitterService(consumer key,secret,token,token);
tweetid.Items.Clear();
ListBox2.Items.Clear();
IEnumerable<TwitterStatus> anasayfa = servis.ListTweetsOnHomeTimeline(new ListTweetsOnHomeTimelineOptions { Count = 200 });
var gelen = servis.ListTweetsOnHomeTimeline(new ListTweetsOnHomeTimelineOptions { Count = 200, MaxId = anasayfa.Last().Id });
foreach (var tweet in gelen)
{
tweetid.Items.Add(tweet.Id.ToString());
ListBox2.Items.Add(tweet.Text);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
servis.Retweet(new RetweetOptions() { Id = long.Parse(tweetid.Items[ListBox2.SelectedIndex].ToString())});
String uyarı = "alert('Retweetlendi!');";
ClientScript.RegisterOnSubmitStatement(this.GetType(), "ConfirmSubmit", uyarı);
}
}
The problem here is that you have two ListBoxes, one (tweetid) storing the id's (presumably a key of sorts) of the tweets, and the other (ListBox2) storing the text of the tweets. You also don't seem to be adding the dynamically created tweetid ListBox to the page anywhere (and presumably the intention is that the tweetid ListBox is hidden or similar).
You are then attempting to store synchronize the selected text drop down back to the original tweetid in the code behind Button click handler, based on the relative indexes of the data - it is apparant that the two listboxes are getting out of synch, plus, you aren't validating the user has selected a valid item, hence the ArgumentOutOfRange exception.
Although in theory this could be made to work, e.g. by ensuring that the data isn't lost in each page_load roundtrip as per #Dan's answer, and also by enabling ViewState, this all seems rather fragile to me.
I would propose that instead, you use a single ListBox and use the DataTextField to show the tweet to the user, and the DataValueField to track the Id of each tweet:
.aspx
<asp:ListBox runat="server" ID="TweetsListBox" DataTextField="Text" DataValueField="Id" EnableViewState="True" />
.aspx.cs Code Behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Replace with your code to fetch tweets here
TweetsListBox.DataSource = FetchSomeTweets();
// We've alread set the names of the properties to use `Id` and `Text` in the aspx
TweetsListBox.DataBind();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
long tweetIdToRetweet;
if (long.TryParse(TweetsListBox.SelectedValue, out tweetIdToRetweet))
{
servis.Retweet(new RetweetOptions() { Id = tweetIdToRetweet });
}
else
{
// Display Error that user must select a tweet
}
}
For test purposes, I used the following mock models for your tweet service:
class Tweet
{
public int Id { get; set; }
public string Text { get; set; }
}
private static readonly IEnumerable<Tweet> SomeTweets = new[]
{
new Tweet { Id = 123, Text = "This is tweet 123" },
new Tweet { Id = 234, Text = "This is tweet 234" },
new Tweet { Id = 345, Text = "This is tweet 345" }
};
Your Page_Load method is populating the ListBox everytime the page postback, even before your button click event.
Thus, ListBox2.SelectedIndex will not be the the index that the user selected, since it is freshly populated in the Page_Load method.
You should add a postback check on your page_load and only populate the ListBox if the request is not a postback.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack) {
servis = new TwitterService(consumer key,secret,token,token);
tweetid.Items.Clear();
ListBox2.Items.Clear();
IEnumerable<TwitterStatus> anasayfa = servis.ListTweetsOnHomeTimeline(new ListTweetsOnHomeTimelineOptions { Count = 200 });
var gelen = servis.ListTweetsOnHomeTimeline(new ListTweetsOnHomeTimelineOptions { Count = 200, MaxId = anasayfa.Last().Id });
foreach (var tweet in gelen)
{
tweetid.Items.Add(tweet.Id.ToString());
ListBox2.Items.Add(tweet.Text);
}
}
}
Related
I am building a Point of Sale system on ASP.net. I have a database table called "tblProduct" and I have used Entity Framework to convert it into a class using code first approach. I created a binding list, which holds items, and have bound the ListBox datasource to the binding list. When a person selects a product, the item goes into the binding list and hence is displayed on the ListBox, everything works correctly up until now. My listbox name is "lbProductsChosen", just for reference.
private static BindingList<tblProduct> blProducts = new BindingList<tblProduct>();
protected void Page_Load(object sender, EventArgs e)
{
lbProductsChosen.DataSource = blProducts;
lbProductsChosen.DataTextField = "Description";
CreateTab();
AddProductsToTab();
ButtonResize();
}
However, while trying to make a "Delete" Button, to try and delete a selected item from the ListBox using:
protected void btnDeleteItem_Click(object sender, EventArgs e)
{
tblProduct selectedItem = (tblProduct)lbProductsChosen.SelectedItem;
blProducts.Remove(selectedItem);
}
It gives me an error and tells me that it "Cannot convert type 'System.Web.UI.WebControls.ListItem' to 'Restoraunt_POS.tblProduct'"
Edit: Here is my button click event, just for clarity. When a product button is pressed, it holds the information in its attributes properties, makes a new instance of the tblProduct class and puts it in the binding list(blProducts).
private void ProductButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
string description = b.Attributes["data-name"];
decimal price = Convert.ToDecimal(b.Attributes["data-price"]);
int productID = Convert.ToInt32(b.Attributes["data-prodID"]);
int prodType = Convert.ToInt32(b.Attributes["data-prodType"]);
tblProduct p = new tblProduct() { Description = description , Price = price , ProductID = productID , ProductType = prodType };
blProducts.Add(p);
lbProductsChosen.Items.Clear();
lbProductsChosen.DataBind();
}
I created some ImageButtons in code-behind.
Then, populated a list of ImageButtons as:
protected void Image_Click(object sender, ImageClickEventArgs e)
{
ImageButton imgButton = sender as ImageButton;
imgButton.ImageUrl = Resource.TICK_IMAGE;
// some work
ImageButtonList.Add(imgButton);
}
On my ASPX page some images will appear now.
After some time, I want to remove those images.
I tried something like:
buttonList.Clear();
But, still the images are appearing on the ASPX page. How should I remove those images?
My whole code looks like:
public static List<Image> RandomImages = new List<Image>();
protected void Page_Load(object sender, EventArgs e)
{
buttonList.Clear();
if (!string.IsNullOrEmpty(Request.Form[Resource.RESET_BUTTON_ID]) || !Page.IsPostBack)
{
RandomImages = ResetGame();
}
AddCardsToDisplay(RandomImages, CardDiv, true);
}
public void AddCardsToDisplay(List<Image> Images, System.Web.UI.HtmlControls.HtmlGenericControl DivisionName, bool isClickable)
{
foreach (var image in Images)
{
ImageButton button = Utilities.CreateImageButton(image.NewImageURL, image.ID, CardDiv);
AddImageButtonClickEvent(button, isClickable);
}
}
protected List<Image> ResetGame()
{
NumberOfClicks = 0;
return GetRandomImages(NUMBER_OF_IMAGES);
}
public static ImageButton CreateImageButton(string imageUrl, string id, System.Web.UI.HtmlControls.HtmlGenericControl DivisionName)
{
ImageButton button = new ImageButton { ImageUrl = imageUrl, ID = id };
DivisionName.Controls.Add(button);
return button;
}
Just use the command "Clear" from your list. To empty the usages pf those buttons. Do that instead of your foreach loop
ImageButtonList.Clear();
And it should work. :-)
EDIT
I thought that the imagelist was the parent of those controls. But it does not seem to be the case.
If you want to remove the button itself, try do something as:
imgButton.Parent.Controls.Remove(imgButton);
If you want to just hide them. Then do
imgButton.Visible = false;
Last but not least. You can reset the image url, set it to null. And it shouldmt be visible (not sure if it will give you a red x though)
I'm setting some default value for my text fields and those fields are in read only mode. When I pass new values to the those fields and submits the form it saved default value not the new one. I have used PostBack function but it's not working. Here is my code,
protected void Page_Load(object sender, EventArgs e)
{
if (! this.IsPostBack)
{
MakeReadControl();
}
}
private void MakeReadControl()
{
((TextBox)this.FindControl("txtMedicalCheckup")).Text = System.DateTime.Now.ToShortDateString();
((TextBox)this.FindControl("txtBosiet")).Text = System.DateTime.Now.ToShortDateString();
((TextBox)this.FindControl("txtLandSurvival")).Text = System.DateTime.Now.ToShortDateString();
((TextBox)this.FindControl("txtDefensiveDriving")).Text = System.DateTime.Now.ToShortDateString();
((DropDownList)this.FindControl("comboDrivingLicense")).SelectedIndex = 1;
((TextBox)this.FindControl("txtOtherLicense")).Text = "Not available";
}
However, the drop down list updates the value correctly.
Update:-
Instead of Read Only attribute if I use enable attribute then it works fine.
I have the following code:
<asp:BulletedList ID="filingList" runat="server" DisplayMode="LinkButton"
onclick="filingList_Click">
</asp:BulletedList>
<asp:Literal ID="filingLiteral" runat="server"></asp:Literal>
and in the backend I fill the bulleted list with ListItems (where AlternateFileUrl is a url string that points to text formatted in html):
foreach (ShortFiling file in filingArray)
{
filingList.Items.Add(new ListItem(file.Type.ToString() + " "
+ file.Date.ToString(), file.AlternateHtmlFileUrl));
}
How do I access the text of the value of the item that's clicked on in the filingList then set it to the asp:Literal control? Here is the empty event handler that I defined and assume that I need to put the code in to set the asp:literal to the value of the specified ListItem.
protected void filingList_Click(object sender, BulletedListEventArgs e)
{
//put code here to set the asp:Literal text to
//the value of the item that is clicked on
}
protected void filingList_Click(object sender, BulletedListEventArgs e)
{
var value = filingList.Items[e.Index].Value;
filingLiteral.Text = value;
}
UPDATE 2
Ok you want the text from that URL, keep your markup as it was and change the code behind to this:
protected void filingList_Click(object sender, BulletedListEventArgs e)
{
var value = filingList.Items[e.Index].Value;
using(var client = new WebClient())
{
string downloadString = client.DownloadString(value);
filingLiteral.Text = downloadString;
}
}
You will need to add the System.Net namespace.
If I have understood your question correctly, you would just handle the click event of the BulletedList control, like:
protected void filingList_Click(object sender, BulletedListEventArgs e)
{
BulletedList bull = (BulletedList)sender;
ListItem li = bull.Items(e.Index);
filingLiteral.Text = li.Value;
}
I have to set a LinkButton's OnClientClick attribute but I don't know what this value is until the LinkButton is bound to. I'm trying to set the value when the repeater binds, but I can't workout how to get the 'boundItem/dataContext' value...
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:LinkButton Text="HelloWorld" ID="Hyper1" runat="server" OnDataBinding="Repeater1_DataBinding" >
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
protected void Page_Load(object sender, EventArgs e)
{
var list = new List<TestObject>();
list.Add(new TestObject() {TestValue = "testing1"});
list.Add(new TestObject() { TestValue = "testing2" });
list.Add(new TestObject() { TestValue = "testing3" });
this.Repeater1.DataSource = list;
this.Repeater1.DataBind();
}
public void Repeater1_DataBinding(object sender, EventArgs e)
{
var link = sender as HyperLink;
//link.DataItem ???
}
Is there anyway to find out what the current rows bound item is?
Maybe you need to use ItemDataBound event. It provides RepeaterItemEventArgs argument which has DataItem available
this.Repeater1.ItemDataBound += Repeater1_ItemDataBound;
void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var dataItem = e.Item.DataItem;
}
I assume you are trying to get the value for the row that is currently being databound?
You can change your function to:
public void Repeater1_DataBinding(object sender, EventArgs e)
{
var link = sender as HyperLink;
string valueYouWant = Eval("TestValue").ToString();
// You could then assign the HyperLink control to whatever you need
link.Target = string.Format("yourpage.aspx?id={0}", valueYouWant);
}
valueYouWant now has the value of the field TestValue for the current row that is being databound. Using the DataBinding event is the best way to do this compared to the ItemDataBound because you don't have to search for a control and localize the code specifically to a control instead of a whole template.
The MSDN library had this as a sample event handler:
public void BindData(object sender, EventArgs e)
{
Literal l = (Literal) sender;
DataGridItem container = (DataGridItem) l.NamingContainer;
l.Text = ((DataRowView) container.DataItem)[column].ToString();
}
(see http://msdn.microsoft.com/en-us/library/system.web.ui.control.databinding.aspx)
As you can see it is a simple demonstration of how to access the data item and get data from it. Adapting this to your scenario is an exercise left to the reader. :)