.Net Webform losing data - c#

I am having problems getting my page to maintain state. View state is enabled by default but everytime I click a button it resets the form. This is the code I have
protected void Page_Load(object sender, EventArgs e)
{
Levels loadGame = new Levels(currentGame);
int [] gameNums = loadGame.getLevelNums();
int inc = 1;
foreach(int i in gameNums){
if (i != 0)
{
TextBox tb = (TextBox)FindControl("TextBox" + inc);
tb.Text = i.ToString();
tb.Enabled = false;
}
else {
//leave blank and move to next box
}
inc++;
}
This is the initial load
protected void NormalButton_Click(object sender, EventArgs e)
{
clearBoxes();//clear boxes first
setCurrentGame("normal");//setting to normal returns normal answers
Levels loadGame = new Levels(returnCurrentGame());
int[] gameNums = loadGame.getLevelNums();
int inc = 1;
foreach (int i in gameNums)
{
if (i != 0)
{
TextBox tb = (TextBox)FindControl("TextBox" + inc);
tb.Text = i.ToString();
tb.Enabled = false;
}
else
{
//leave blank and move to next box
}
inc++;
}
}
Clicking this button changes the numbers in different boxes.
protected void Button1_Click(object sender, EventArgs e)
{
}
Then I have this empty button but everytime I click it, it resets the form even though I havent set it to do anything yet. I would like the boxes to stay the same and I would also like to keep the objects alive. I'm not sure what I'm missing but please point me in the right direction. Thanks in advance

The Page_Load event occurs every time the page is loaded, including event-driven postbacks (button clicks, etc).
It looks like initialization code is in your Page_Load, so when you click the button it runs again.
There are two options:
Put everything that you want to happen only on the FIRST load in a n if statement:
Move your initialization to Page_Init.
Code sample for the first option:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) // Teis is the key line for avoiding the problem
{
Levels loadGame = new Levels(currentGame);
int [] gameNums = loadGame.getLevelNums();
int inc = 1;
foreach(int i in gameNums){
if (i != 0)
{
TextBox tb = (TextBox)FindControl("TextBox" + inc);
tb.Text = i.ToString();
tb.Enabled = false;
}
else {
//leave blank and move to next box
}
inc++;
}
}
}
Also, recommended reading: The ASP.NET Page Lifecycle

Related

Updating a label using a for statement (typewriter effect)

I'm developing a game in Windows Forms (.NET-framework), and I want to add a typewriter effect to the text I'm displaying (so that it displays letter by letter). I'm using a for-loop for this. The text is displayed in a label.
I have 2 variables. 1 that holds all the text, and one that holds the text that needs to be printed out in the loop:
public string FullText;
private string CurrentText = "";
The label that I want to update with the loop is called: LblTextBottom
This is the method that gets executed when I click on the appropriate button:
public void TypeWriterEffect()
{
for(int i=0; i < FullText.Length; i++)
{
CurrentText = FullText.Substring(0, i);
LblTextBottom.Text = CurrentText;
Thread.Sleep(10);
}
}
This is the code that is activated when I click on the button to run the TypeWriterEffect method:
private void Button1_Click(object sender, EventArgs e)
{
FullText = LblTextBottom.Text;
ShowText();
}
It updates the Label, and the code works, but I don't see it updating in real time (the text doesn't get displayed letter by letter). I've tried using separate threads to update the control, but I didn't get that to work.
Ofcourse, I wouldn't be here if this code was working. But I don't know why it won't update. So any help would be greatly appreciated :)
P.s: This is what I'm looking for, but ofcourse without the UnityEngine classes and namespace (can't use those).
EDIT: Forgot to tell that when a button is clicked, a new string of text is loaded into the LblTextBottom, from a different .cs file.
If you write it generically, then you can have multiple typewriters going at the same time:
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
await TypeWriterEffect("This is some text to be `typed`...", LblTextBottom, 100);
button1.Enabled = true;
}
private async void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
await TypeWriterEffect("Look mom, we're running at the same time!!!", label2, 200);
button2.Enabled = true;
}
public Task TypeWriterEffect(string txt, Label lbl, int delay)
{
return Task.Run(() =>
{
for (int i = 0; i <= txt.Length; i++)
{
lbl.Invoke((MethodInvoker)delegate {
lbl.Text = txt.Substring(0, i);
});
System.Threading.Thread.Sleep(delay); ;
}
});
}
Producing:

how to set event click when click editor button

i cant call or use event click of editor button that i create. the screen shot for the button is
the code that i make is like this
RepositoryItemComboBox repositoryItemComboBox1 = new RepositoryItemComboBox();
EditorButton lp = new EditorButton();
private void gridView1_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
repositoryItemComboBox1.Items.Clear();
GridView view = sender as GridView;
for (int i = 0; i < gridView1.RowCount; i++)
{
if (gridView1.GetDataRow(i) == null)
{
break;
}
string code = gridView1.GetDataRow(i)["code"].ToString();
if (!repositoryItemComboBox1.Items.Contains(code))
{
repositoryItemComboBox1.Items.Add(code);
}
}
if (e.Column.FieldName == "code" && view.IsFilterRow(e.RowHandle))
{
repositoryItemComboBox1.Buttons.Add(lp);
repositoryItemComboBox1.Buttons[0].Kind = DevExpress.XtraEditors.Controls.ButtonPredefines.Plus;
repositoryItemComboBox1.Buttons[1].Kind = DevExpress.XtraEditors.Controls.ButtonPredefines.Minus;
e.RepositoryItem = repositoryItemComboBox1;
}
when i click the minus nothing happen because no handler(event).
what i want is when i click that minus button it clear gridview filter
FYI : iam using devexpress
You can hook to the repositoryItem's ButtonClick event. In this event, you will know which button has been clicked. So let's say you create your button this way :
private void SomeMethod()
{
var buttonPlus = new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Plus);
var buttonMinus = new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Minus);
repositoryItemComboBox1.Buttons.Add(buttonPlus);
repositoryItemComboBox1.Buttons.Add(buttonMinus);
}
In the repositoryItemComboBox1_ButtonClick, you have access to the button properties in the "e" argument. In this example, i'm using the "Kind" property, but you could use the tag or anything really.
private void repositoryItemComboBox1_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
{
if (e.Button.Kind == DevExpress.XtraEditors.Controls.ButtonPredefines.Minus)
{
// do something
}
else if (e.Button.Kind == DevExpress.XtraEditors.Controls.ButtonPredefines.Plus)
{
// do something else
}
}
This is the way I do it.

How to use dynamic button click event handler without using page init or page load

I am trying to figure out how to use a click event handler for my 4 buttons that I have generated dynamically without putting any code in page init or oninit. I have one button that once clicked it generates 4 more buttons. The click event handler for these 4 buttons is not working. Here is the code. Has anybody figured out a way to use the click events in asp.net c# without first putting it in page_load? If I can solve this problem, I can solve my real problem in a bigger scenario.:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 4; i++)
{
Button b = new Button();
b.ID = i.ToString();
b.Text = "ClickMe";
b.Visible = true;
b.Click += new EventHandler(b_click);
PlaceHolder1.Controls.Add(b);
}
}
void b_click(object sender,EventArgs e)
{
Label1.Text = "ok";
}
Make sure the ID of your dynamic controls include a distinct keyword. In my example below I prepended "DYNAMIC_" to their ID. Then override OnPreRender() like this:
protected override void OnPreRender(EventArgs e)
{
if (Page.IsPostBack && !IsPostBackEventControlRegistered)
{
var controlName = this.Request.Form.AllKeys.SingleOrDefault(key => key.Contains("DYNAMIC_"));
processEventForDynamicControl(controlName);
}
base.OnPreRender(e);
}
private void processEventForDynamicControl(string controlName)
{
//Do your dynamic button click processing here
}
Of course, if your dynamic controls use doPost() (which sadly Button doesn't) you can retrieve the control directly from __EVENTTARGET like this:
var controlName = Request.Params.Get("__EVENTTARGET")
You want to load controls inside Page_Load. Otherwise, they are not in control tree, and they won't be able to trigger b_click event.
public int Counter
{
get { return (int?) ViewState["Counter"] ?? 0; }
set { ViewState["Counter"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
var counter = Counter;
for (int i = 0; i < counter; i++)
{
Button b = new Button();
b.ID = i.ToString();
b.Text = "ClickMe";
b.Visible = true;
b.Click += b_click;
PlaceHolder1.Controls.Add(b);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Counter = 4;
for (int i = 0; i < 4; i++)
{
Button b = new Button();
b.ID = i.ToString();
b.Text = "ClickMe";
b.Visible = true;
b.Click += b_click;
PlaceHolder1.Controls.Add(b);
}
}
void b_click(object sender, EventArgs e)
{
Label1.Text = "ok";
}
Note: If you plan to load inside Page_Init, you want to use Session instead of ViewState.
Basically I got it working.There is no way around it. You have to use Oninit or Page_load and put your b.Click += new EventHandler(b_click) code there in addition to the PlaceHolder1.Controls.Add(b); there as well,for the event handler to register properly with the button. The problem with this method is that it places the button on top of the PlaceHolder portion of the web page which is not what I want. I want to beable to place the button at a particular position in the web page. So how do you go around doing this? Basically after the PlaceHolder1.Controls.Add(b) simply make the button invisible. Then in the when you are ready to place the button in a particular part of your html call PlaceHolder1.Controls.Add(b) again and make it visible. That works for me. If anyone needs help with this I can post some sample code and you can test it for yourself. Thanks all.

Why does my dynamic textbox not remove on first click?

I started this question and was able to get an answer to my original question. Now the textbox gets removed but only the second time I click the remove button. Here is what I have tried
protected void btnRemoveTextBox_Click(object sender, EventArgs e)
{
foreach (Control control in PlaceHolder1.Controls)
{
var tb = new TextBox();
tb.ID = "Textbox" + counter;
if ((control.ID == tb.ID.ToString()) && (control.ID != null))
{
controlIdList.Remove(tb.ID);
ViewState["controlIdList"] = controlIdList;
}
}
}
When I step through using breakpoints and error debugging the code runs through twice without error however on the second time through it removes the button.
Because you created and added textboxes in LoadViewState method (earlier in the the page's life cycle), and here only remove an id from controlIdList but not from the control tree. Note: you do not need to create new TextBox instances in btnRemoveTextBox_Click method.
protected void btnRemoveTextBox_Click(object sender, EventArgs e)
{
foreach (Control control in PlaceHolder1.Controls)
{
string id = "Textbox" + counter;
if (control.ID == id)
{
controlIdList.Remove(id);
PlaceHolder1.Controls.Remove(control);
break;
}
}
}

ASP.NET dynamic controls count (creating controls as you go)

I'm trying to create a composite ASP.NET control that let's you build an editable control collection.
My problem is that when I press the add or postback button (which does nothing other than to postback the form) any values entered in the text boxes are lost.
I can't get it to work when the number of controls change between postbacks. I need to basically be able to recreate the control tree at two different times in the control life-cycle depending on the view state property ControlCount.
This test can be used to reproduce the issue:
public class AddManyControl : CompositeControl
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
}
protected override void CreateChildControls()
{
var count = ViewState["ControlCount"] as int? ?? 0;
for (int i = 0; i < count; i++)
{
var div = new HtmlGenericControl("div");
var textBox = new TextBox();
textBox.ID = "tb" + i;
div.Controls.Add(textBox);
Controls.Add(div);
}
ViewState["ControlCount"] = count;
var btnAdd = new Button();
btnAdd.ID = "Add";
btnAdd.Text = "Add text box";
btnAdd.Click += new EventHandler(btnAdd_Click);
Controls.Add(btnAdd);
var btnPostBack = new Button();
btnPostBack.ID = "PostBack";
btnPostBack.Text = "Do PostBack";
Controls.Add(btnPostBack);
}
void btnAdd_Click(object sender, EventArgs e)
{
ViewState["ControlCount"] = (int)ViewState["ControlCount"] + 1;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// If I remove this RecreateChildControls call
// the collection lags behind each postback
// because the count is incremented in the btnAdd_Click event handler
// however, the values are not lost between postbacks
RecreateChildControls();
}
}
If you want to play with ASP.NET's custom controls, you have to play by its rule and its picky! When you start to play with the OnPreRender in a custom control, you know you're on the wrong track 90% of the time.
Generally, the best way to use the ViewState is to declare a property backed up by it, just like the standard ASP.NET controls do (.NET Reflector has been my teacher for years!). This way, it will be read and saved naturally during the event's lifecycle.
Here is a code that seems to do what you want, quite naturally, without any trick:
public class AddManyControl : CompositeControl
{
private void AddControl(int index)
{
var div = new HtmlGenericControl("div");
var textBox = new TextBox();
textBox.ID = "tb" + index;
div.Controls.Add(textBox);
Controls.AddAt(index, div);
}
protected override void CreateChildControls()
{
for (int i = 0; i < ControlsCount; i++)
{
AddControl(i);
}
var btnAdd = new Button();
btnAdd.ID = "Add";
btnAdd.Text = "Add text box";
btnAdd.Click += new EventHandler(btnAdd_Click);
Controls.Add(btnAdd);
var btnPostBack = new Button();
btnPostBack.ID = "PostBack";
btnPostBack.Text = "Do PostBack";
Controls.Add(btnPostBack);
}
private int ControlsCount
{
get
{
object o = ViewState["ControlCount"];
if (o != null)
return (int)o;
return 0;
}
set
{
ViewState["ControlCount"] = value;
}
}
void btnAdd_Click(object sender, EventArgs e)
{
int count = ControlsCount;
AddControl(count);
ControlsCount = count + 1;
}
}
I believe you have to add the control into the view state.

Categories