Cannot get Textboxes in dynamically added usercontrol to maintain state - c#

I have tried what seems like everything - I've done similiar things many times before, but I'm obviously missing something.
I have a UserControl (ucA) - on ucA is a LinkButton that loads a different UserControl (ucB) programatically into a panel on ucA. ucB has TextBoxes, etc.
Why isn't my control maintaining it's state? ie: The textboxes are loosing thier value on postback - the control tree shows the name of the control and the Form values show the value (in trace.axd)
Here is the code for ucA (basically)
public int SlideCount
{
get { return Convert.ToInt32(ViewState["SlideCount"]); }
set { ViewState["SlideCount"] = value; }
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
SlideCount += 1;
LoadSlideControls();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
LoadSlideControls();
}
private void LoadSlideControls()
{
this.pnlAnnouncementHolder.Controls.Clear();
for (int i = 0; i < SlideCount; i++)
{
this.pnlAnnouncementHolder.Controls.Add(
LoadControl("AnnouncementSlide.ascx"));
}
}
Heres a full example of what im trying to do:
http://keithsblogs.com/ControlTest2.zip
The problem Vyrotek points out is that the control is added a little to late to the lifecycle on the click event - anyone have any ideas?

I just tried to recreate what you have setup and I dont seem to experience the same problem. Would you like me to send you my Solution somehow?
Final Edit, I promised -
Try this solution: http://www.vyrotek.com/code/ControlTest2.zip

I am installing express edition as I type. By that time, why should you clear the controls on click of the button? cant you just add/load the uc once control on click of the link?
By doing this, you would not be clearing the old controls and they would retain the value.

Related

C# Execute Method for selected CheckBoxes. Different Method for each CheckBox

So I have a bunch of CheckBoxes on a Form with a Button at the bottom that I want to click and it Executes the Methods for those Checked CheckBoxes.
Each CheckBox will use its own Method.
Seems Like a Common/Simple thing to do. Yet I have found nothing too helpful searching around regarding dealing with multiple CheckBoxes on one Event.
I am relatively new to programming and I'm learning on my own.
Idk if there's a simple for or foreach loop I can use in conjunction with something else to make this simpler, but I don't even know a long way to make it work...
All I can Come up with is a bunch of if statements under button click event to test if checked and if so run method. However, this seems like the wrong way to do this.
private void btnExecutedSelected_Click(object sender, EventArgs e)
{
if (ChkBox_Test.Checked == true)
{
ClassName.MethodName();
}
//Then an if statement for each CheckBox
}
Any Help Much Appreciated
There are several ways to approach this, and usually the best ways are a little more advanced, but this is a good opportunity to learn some basics about delegates, which are like a mix between variables and methods/functions. For now, think of them like a card in Monopoly that tells you to go directly to jail. The card itself isn't really anything except an instruction that you pick up. When you USE / read the card, you have to follow the resulting instruction, which is to go to jail. So delegates are sort of like those cards.
To get an idea of how they work, create a new Winforms app, drop 4 checkboxes on the form and a button. Don't worry about renaming them. Then add in the following code:
// This defines the "monopoly cards"
// Community Chest cards give or take money, so we'll expect an int to be returned
public delegate int CommunityChestCard();
// Chance cards just do things without any return values
public delegate void ChanceCard();
private void Form1_Load(object sender, EventArgs e)
{
checkBox1.Tag = new ChanceCard(GoDirectlyToJail);
checkBox2.Tag = new ChanceCard(AdvanceToGo);
checkBox3.Tag = new CommunityChestCard(WinBeautyContest);
checkBox4.Tag = new CommunityChestCard(PayDoctorsFees);
}
private void GoDirectlyToJail()
{
MessageBox.Show("You went to jail!");
}
private void AdvanceToGo()
{
MessageBox.Show("You advanced to Go!");
}
private int WinBeautyContest()
{
MessageBox.Show("You won $20 in a beauty contest!");
return 20;
}
private int PayDoctorsFees()
{
MessageBox.Show("You had to pay $50 in doctor's fees!");
return -50;
}
// Now when we click the button, we'll loop through our checkboxes,
// see which ones were checked, and then execute the methods defined
// in the associated chance/communitychest cards.
private void button1_Click(object sender, EventArgs e)
{
// this.Controls is a collection of the child controls on the current form
foreach(Control ctl in this.Controls)
{
// See if the control is a CheckBox
if(ctl is CheckBox)
{
// It is - let's cast it for easier coding...
CheckBox chk = (CheckBox)ctl;
// Is it checked?
if (chk.Checked)
{
// Yep! Does it have a value in its Tag?
if (chk.Tag != null)
{
if(chk.Tag is CommunityChestCard)
{
CommunityChestCard ccCard = (CommunityChestCard)chk.Tag;
// Call the function on the card and get the result
int adjustMoneyByAmount = ccCard();
}
else if(chk.Tag is ChanceCard)
{
ChanceCard cCard = (ChanceCard)chk.Tag;
// Call the function on the card
cCard();
}
}
}
}
}
}
Now, just some words of warning - I used the Tag property as a quick fix to cut down on extra coding for illustration purposes. As you get better with code and custom/extended controls, you might want to have your own properly-typed properties for these kinds of things. Using Tag is NOT an elegant solution.
If you run that code as described, you should be able to check some of the checkboxes and click the button and see the resulting functions being executed.
I'd also suggest not just looping through all the controls on a form and checking to see if they're checkboxes. You seemed to have some trouble with looping through controls, so that approach was there as an example. Checkboxes can be grouped together in many different ways. You might consider a List object and adding your checkboxes to that list. That way, you can simply loop through that List later and you'll know exactly which controls you're dealing with (no ugly casting or checking to see if a control is a checkbox).
You can do something like this:
private void CheckBoxOperations(Control parentControl)
{
foreach (Control c in parentControl.Controls)
{
if (c is CheckBox)
{
if (((CheckBox)c).Checked)
{
//DoSomething
}
}
if (c.HasChildren)
{
CheckBoxOperations(c);
}
}
}
private void btnExecutedSelected_Click(object sender, EventArgs e)
{
CheckBoxOperations(this);
}

ComboBox show dropdown menu on text selection

I want to show the list of items in a combo box when the user selects the text. I have a touch screen application and it's very difficult to hit the dropdown arrow so I figure I'd show the menu when the text is selected which is often what gets touched. I'm using VS 2008. and suggestions for a touch friendly numeric up down solution in VS2008?
You could use the ComboBox.Click event handler and the ComboBox.DroppedDown property and do something like this:
private void ComboBox1_Click(System.Object sender, System.EventArgs e)
{
ComboBox1.DroppedDown = true;
}
You could also use the same event handler for a numericUpDown and use the mouseposition as well as the position and height of the NumericUpDown to get whether or not the click was above or below the halfway-line of the control by doing something like this (not sure if my math here is perfect, but it worked when I tested it):
if ((MousePosition.Y - this.PointToScreen(NumericUpDown1.Location).Y < NumericUpDown1.Height / 2))
{
NumericUpDown1.Value += 1;
}
else
{
NumericUpDown1.Value -= 1;
}
HTH
I was working on a similar situation. We wanted to make the text area behave the same as the button on the right. (IE the user clicks and gets the drop down box)
davidsbro is similar to what I ended up doing, but we wanted it to close if they clicked again, so the value became dropDown.DroppedDown = !dropDown.DroppedDown;.
The issue with this is that if the user clicks the right button of the drop down box, the dialog box opens, then calls the onClick event.
I solved this situation by tracking the original state via the onmouseover event. If the value has changed, we have to assume that the button on the select box handled the click already.
private bool cbDropDownState = false;
private void dropDown_MouseEnter(object sender, EventArgs e)
{
cbDropDownState = dropDown.DroppedDown;
}
private void dropDown_Click(object sender, EventArgs e)
{
if (dropDown.DroppedDown == cbDropDownState )
dropDown.DroppedDown = !dropDown.DroppedDown;
}

Find Control in collection - event ControlAvailable Disabled

In my lightswitch app i need to add a small image control to every row, when clicking on it , it should send you to a detail screen. I made the silverlight control and added it to the lightswitch app.
partial void VidContentItemRessources_Loaded(bool succeeded) {
int index = 0;
foreach (VidContentItemRessourcesItem cust in this.VidContentItemRessources) {
this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index))
.ControlAvailable += (s, e) => {
MyLinkImage = (e.Control as LinkImage);
MyLinkImage.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
};
index++;
}
}
But if i do this i get an error that the event control available can't be used on controls in collection ..
So i tried to do it like this
LinkImage neco = this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index)) as LinkImage;
neco.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
But then neco is allways null because it is trying to load the control before it's available... any solution pls ?
These types of initialisations should go in the screen's Created method, that way you're guaranteed that all of the controls on the screen have been created. If any of the screen's methods (like InitializeDataWorkspace, Created, Saving etc) aren't in your code file, you can create them by using the Write Code dropdown box in the screen editor.
I solved it like this:
I catching click event in silverlight control than i invoking method in lightsiwtch
public void MouseClick(object sender, MouseButtonEventArgs e) {
var objDataContext = (IContentItem)this.DataContext;
var Screen = (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
Screen.Details.Dispatcher.BeginInvoke(() => {
Screen.Details.Methods["DoImageLinkEvent"]
.CreateInvocation(null).Execute();
});
}

How to find a control inside an asp.net calendar control

After adding a control in the dayrender event, is there a way to find the control later? I have tried
calendar.FindControl("lblSample")
but without success.
Here is some of my code to be more clear:
protected void calSample_DayRender(object sender, DayRenderEventArgs e)
{
Label lblSample = new Label();
lblSample.ID = "lblSample";
lblSample.Text = "Sample";
e.Cell.Controls.Add(lblSample);
}
After the day render event and the page loads completely, I have a link button event where I try and get the control back
protected void lbtnSave_Click(object sender, EventArgs e)
{
//Not working
Label lblSample = calSample.FindControl(lblSample);
//Also can't get to work, this was using Ross' suggestion and the recursive find function he wrote about. I'm probably just not using it correctly.
Label lblSample = ControlFinder.FindControl<Label>(calSample, "lblSample");
}
The issue was because the control was not added to the page until the dayrender method - meaning you could not get a reference to it on a post back. Using the Page.Request.Params collection the OP was able to grab the value out on the postback.
The problem is that the find control is not recursive and the control you want is probably inside another control.
This shows you how to make a recursive find control method that would help: http://stevesmithblog.com/blog/recursive-findcontrol/
Alternatively if you post the calendar controls code I can probably help you a bit more.
Ross
This answer is because of Ross' comment above showing me that I could use the Page.Request.Params to find the value I was after. It's not the cleanest solution but it works!
If you add a dropdownlist to a calendar control in the day render event
protected void calSample_DayRender(object sender, DayRenderEventArgs e)
{
DropDownList ddlSample = new DropDownList();
ddlSample.ID = "ddlSample";
ddlSample.DataSource = sampleDS;
ddlSample.DataBind();
e.Cell.Controls.Add(ddlSample);
}
You can get the selected value back like this, of course I need to put in more checks to verify that the dropdownlist exists, but you get the picture
protected void lbtnSave_Click(object sender, EventArgs e)
{
string sampleID = Page.Request.Params.GetValues("ddlSample")[0];
}

How do I dynamically create/remove controls, with EventHandlers, to/from an ASP.NET page?

In one of my projects I need to build an ASP.NET page and some of the controls need to be created dynamically. These controls are added to the page by the code-behind class and they have some event-handlers added to them. Upon the PostBacks these event-handlers have a lot to do with what controls are then shown on the page. To cut the story short, this doesn't work for me and I don't seem to be able to figure this out.
So, as my project is quite involved, I decided to create a short example that doesn't work either but if you can tweak it so that it works, that would be great and I would then be able to apply your solution to my original problem.
The following example should dynamically create three buttons on a panel. When one of the buttons is pressed all of the buttons should be dynamically re-created except for the button that was pressed. In other words, just hide the button that the user presses and show the other two.
For your solution to be helpful you can't statically create the buttons and then use the Visible property (or drastically change the example in other ways) - you have to re-create all the button controls dynamically upon every PostBack (not necessarily in the event-handler though). This is not a trick-question - I really don't know how to do this. Thank you very much for your effort. Here is my short example:
From the Default.aspx file:
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="ButtonsPanel" runat="server"></asp:Panel>
</div>
</form>
</body>
From the Default.aspx.cs code-behind file:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DynamicControls
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
AddButtons();
}
protected void AddButtons()
{
var lastClick = (string) Session["ClickedButton"] ?? "";
ButtonsPanel.Controls.Clear();
if (!lastClick.Equals("1")) AddButtonControl("1");
if (!lastClick.Equals("2")) AddButtonControl("2");
if (!lastClick.Equals("3")) AddButtonControl("3");
}
protected void AddButtonControl(String id)
{
var button = new Button {Text = id};
button.Click += button_Click;
ButtonsPanel.Controls.Add(button);
}
private void button_Click(object sender, EventArgs e)
{
Session["ClickedButton"] = ((Button) sender).Text;
AddButtons();
}
}
}
My example shows the three buttons and when I click one of the buttons, the pressed button gets hidden. Seems to work; but after this first click, I have to click each button TWICE for it to get hidden. !?
I think that you have to provide the same ID for your buttons every time you add them like this for example (in first line of AddButtonControl method):
var button = new Button { Text = id , ID = id };
EDIT - My solution without using session:
public partial class _Default : Page
{
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
AddButtons();
}
protected void AddButtons()
{
AddButtonControl("btn1", "1");
AddButtonControl("btn2", "2");
AddButtonControl("btn3", "3");
}
protected void AddButtonControl(string id, string text)
{
var button = new Button { Text = text, ID = id };
button.Click += button_Click;
ButtonsPanel.Controls.Add(button);
}
private void button_Click(object sender, EventArgs e)
{
foreach (Control control in ButtonsPanel.Controls)
control.Visible = !control.Equals(sender);
}
}
You need to make sure that your dynamic controls are being added during the Pre_Init event.
See here for the ASP.NET Page Lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx
When adding events you need to do it no later than the Page_Load method and they need to be added every single request, ie you should never wrap event assignment in a !IsPostBack.
You need to create dynamic controls ever single request as well. ViewState will not handle the recreation on your behalf.
One thing I notice is that when you click a button you are invoking AddButtons() twice, once in the Page_Load() and once in the button_Click() method. You should probably wrap the one in Page_Load() in an if (!IsPostBack) block.
if (!IsPostBack)
{
AddButtons();
}
AFAIK, creating of controls should not be placed in Page_Load but in Page_PreInit (ViewState and SessionState is loaded before Page_Load but after Page_PreInit).
With your problem, I would suggest to debug the AddButtons function to find out what exactly (and when) is stored in Session["ClickedButton"]. Then, you should be able to figure out the problem.
the controls that are added dynamically are not cached so this migth me one of your problems

Categories

Resources