Edit (more brief):
I have a control "configuration" with a tree view on the left and a list of panels on the right to which i add my controls. These elements are placed inside a table and surrounded by an ajax panel.
Let's say i have a tree node cars with two elements car1 and car2. When i click an item i save the ID and Type of the selected tree node inside hidden fields to be able to load the right user control on Page_Init
protected void Page_Init(object sender, EventArgs e)
{
var type = this.Request.Form["ctl00$MainContent$ctl00$typeId"];
var id = this.Request.Form["ctl00$MainContent$ctl00$entityId"];
if (!string.IsNullOrEmpty(type) && !string.IsNullOrEmpty(id))
{
this.LoadUserControl(type, id);
}
}
private void LoadUserControl(string type, string id)
{
if (Convert.ToInt32(type) != 0)
{
switch (Convert.ToInt32(type))
{
case (int)SkTopics.Product:
this.AddUserControl("../Modules/Product.ascx", this.Product, type, id);
break;
}
}
}
private void AddUserControl(string controlName, Panel panel, string type, string id)
{
// Init new user cotntrol
control = (BaseControl)this.LoadControl(controlName);
control.LoadEntityItem(Convert.ToInt32(id));
// Setting the user control ID
var replace = controlName.Replace("../Modules/", string.Empty);
string userControlId = replace.Split('.')[0] + id;
var targetControl = panel.FindControl(userControlId);
if (object.Equals(targetControl, null))
{
control.ID = userControlId;
control.DataBind();
panel.Controls.Add(control);
}
}
On LoadEntityItem the data for this car are collected from the database and the values are set as Text of textboxes. When i now switch to the second car, the new values are displayed.
Problem: I change the values inside the textboxes and press the save button to call my save method of the user control. From now on, when i switch to the car 1 again, the values for car 2 are still displayed, although the data for car1 are filled. tO see the data for car1 i have to switch to a complete different type of control and then back to the car1.
Another problem is, that i have a binary image inside the user control which Data i fill on init. When i swith to the the next car, where there i no image configured, i set the image data to null, but the image from the previous car i show. Onyl if i set a different image data the new image is displayed.
There is something else i noticed:
Inside the user control i call a javascript funtion but this one is only called on clicking the the save button. It seems that there is a different between the switch of the tree node and the save button click ?
ScriptManager.RegisterStartupScript(this, this.GetType(), "InitScrewPointsForDragging", "InitScrewPointsForDragging();", true);
I hope this was more brief than before.
It seems that the reason for the issue is some improper viewstate handling and after I disable the view state it is working correctly at my side. Here is the code that I updated to have it work at my side:
this.control.EnableViewState = false;
this.control.ID = userControlId;
Related
I've been searching for a couple of days now and am running into an issue no matter what I've tried. The problem is that I seem to have come across with the perfect storm and I can't get all 3 things working at the same time.
Pagination
Optional Parameters
Parameter Dialog Prompt
So this first method is what I've been using and everything works except it won't Navigate past past 2 (And I've very aware of why navigation doesn't work)
// ##################################################################################################################################################
// METHOD 1: Everything works correctly except you can't go past page 2
protected void Page_Load(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
}
}
So knowing that the common fix is to not use Page Load but use Page_Init instead. This fixes the Navigation... until I open a report that has optional parameters. With those, every time I try to navigate to the next page, instead of it working, the Parameter box re-appears and now requires at least 1 of my Optional Parameters to be filled out. (Each "next Page" reduces the prompt by 1 Optional). But, because I'm being forced to change the Parameters, it "refreshes" the report and I'm back on Page 1.
// ##################################################################################################################################################
// METHOD 2: Works, but not for any report that has Optional Parameters. They become "Required" and keep popping up instead of navigating to the next page
protected void Page_Init(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
}
}
Now, I got real excited, because I got a bit clever and fixed both those issues, by trapping the Navigation and keeping track of the Page myself. EVERYTHING WORKS NOW!!! until I go to the Parameter Dialog prompt and it was totally jacked up.
// ##################################################################################################################################################
// METHOD 3: Everything works correctly except the Prompt Box doesn't Format correcly due to the addition of the added Event Handers
protected void Page_Load(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
//Init our Manual Page Counter to 1
HiddenFieldPageNumber.Value = "1";
}
CrystalReportViewer1.Navigate += CrystalReportViewer1_Navigate; //Simply Adding this event, EVEN IF IT HAS NO CODE, Breaks the style and formating of the Parameter Prompt box.
CrystalReportViewer1.PreRender += CrystalReportViewer1_PreRender;
}
private void CrystalReportViewer1_Navigate(object source, CrystalDecisions.Web.NavigateEventArgs e)
{
//This prevents this event from Incrementing the Page again when the PreRender Event
//below re-sets which page to show.
if (_SkipPageIncrement == true)
{
return;
}
//Whenever the Navigation is used, this Event fires. Here is the problem, there is nothing that actually tells
//us if the user clicked on Previous or Next (or GotoPage for that Matter). So we have to do some guessing here
if (e.CurrentPageNumber == 1 && e.NewPageNumber == 2)
{
//If they pressed "NEXT" we will always get Current = 1 and New = 2 due to the Pagination starting over on the PostBack
//So we INCREMENT our real Page Number Value.
HiddenFieldPageNumber.Value = (Convert.ToInt32(HiddenFieldPageNumber.Value) + 1).ToString();
}
else if (e.CurrentPageNumber == 1 && e.NewPageNumber == 1)
{
//If they pressed "PREV" we will always get Current = 1 and New = 1 due to the Pagination starting over on the PostBack
//So we DECREMENT our real Page Number Value.
HiddenFieldPageNumber.Value = (Convert.ToInt32(HiddenFieldPageNumber.Value) - 1).ToString();
}
}
private void CrystalReportViewer1_PreRender(object sender, EventArgs e)
{
//The Viewer has a method that allows us to set the page number. This PreRender Event is the only
//Event I could find that works. It comes AFTER the Navigate, but before the reports is rendered.
_SkipPageIncrement = true; //The ShowNthPage re-triggers the Navigation, so this prevents it from running again.
CrystalReportViewer1.ShowNthPage(Convert.ToInt32(HiddenFieldPageNumber.Value));
}
As commented above, the moment I add the OnNavigation Event, even if I comment out all the actual code inside, my Prompt box goes from looking like this...
To this (my page as a dark background and you can see that now shows, plus the "OK" button is all jacked up.
I just don't get why trapping the Navigation Event breaks the Prompt box even when the event is not firing (on that first load).
Side note: I'm using VS 2019 with CR 13.0.3500.0
So thanks to the help of a teammate that is more adept on CSS as I am, I have resolved the issue "good enough". So for anyone who wants to use the LOAD event, (Or has to like me), but then loses the ability to use the navigation and wants to use my method, the band-aid for the Crystal Reports Parameter prompt is to simply override their Styling in you Site.css with this...
/*---------------------- Custom CSS for Report Prompt Buttons ----------------------*/
.pePromptButton {
padding-bottom:4.3px;
}
td.pePromptButton {
display: inherit;
}
img {
vertical-align:top;
}
I try the new Shell of Xamarin Form 4 for a small project.
I have a list of order, then someone chooses an order and start picking some inventory for this order with barcode. To be simple, I use 2 views and 2 viewmodel.
The process is:
1. User select an order the click a button "pickup"
2. I use ViewModelLocator (TinyIoc) to resolve the correct ViewModel of the pickup view
3. I call Initialize on the new ViewModel and pass some parameters needed. Like a list of items needed to be pickup.
4. Open the view in modal state.
I don't understand that if I change some qty in the list I pass on the second viewmodel, then hit the back button (modal view close). The quantity changed is now in the original viewmodel. How this is possible? I was thinking that passing parameter to a function do not share the same variable but just copy it??
Viewmodel of the first view (look at the Initialize function the List passed and the JobEnCours object)
private async Task GoPickup()
{
Device.BeginInvokeOnMainThread(async () =>
{
if (this.CodeJob != null && this.CodeJob != "")
{
this.IsBusy = true;
PrepChariotSP3ViewModel vm = ViewModelLocator.Resolve<PrepChariotSP3ViewModel>();
await vm.InitializeAsync(this._jobEnCours, this.ComposantesPick.ToList()) ;
await Shell.Current.Navigation.PushAsync(new PrepChariotSP3Page(vm));
this.IsBusy = false;
}
});
}
the the Initialize code on the second Viewmodel (look I set the JobEnCours.Description=Test)
public async Task InitialiseAsync(Job jobEnCours, List<ComposantePick> composantePick)
{
Title = "Ceuillette: " + jobEnCours.CodeProd;
this._jobEnCours = jobEnCours;
this.ComposantesPick = new ItemsChangeObservableCollection<ComposantePick>();
foreach(ComposantePick c in composantePick)
{
this.ComposantesPick.Add(c);
}
jobEnCours.Description = "test";
So, If I do the back button, then in the first VM the JobEnCours.Description is now set to "test" how this is possible?!
Any idea?
I want to create dynamic text boxes during run time.
Suppose im gettng a text from a database as "# is the capital of India" now i want to replace that "#" by text box while it is rendered to user as below
<asp:TextBox runat="server" id = "someid"></asp:TextBox> is the capital of India
Im able to get the textbox and text as combination. However I cannot access the textboxes with the given id and when any event occurs on the page the textboxes are lost as they logically does not exist untill their state is stored.
I also went through the concepts of place holder and Viewstate to store the dynamically created controls and make their id's available for the methods, but as far as I tried I could not meet the textbox and text combination requirement.
Im looping over the entire text recieved from database and checking if there is any"#". Is yes then i want to replace it with a textbox on which i can call methods to take back the value entered in the text box to database and store it.
eg: text is "#" is the capital of India
for (int i = 0; i < que.Length; j++) //que holds the text
{
if (que[i] == '#')
{
//Textbox should be created
}
else
{
//the texts should be appended before or after the textbox/textboxes as text demands
}
}
On button click I'm passing request to database, which will send me necessary details i.e. question text, options and also saves the current checked value etc.
protected void BtnLast_Click(object sender, EventArgs e)
{
CheckBox1.Checked = false;
CheckBox2.Checked = false;
CheckBox3.Checked = false;
CheckBox4.Checked = false;
QuestionSet q = new QuestionSet();
StudentB b = new StudentB();
q = b.GetQuestion(1, 1, qid, 'L', 0, Checked, date);
qid = Convert.ToInt32(q.Question_Id);
Checked = q.Checked;
if (q.Question_Type == 11) //indicates its objective Question
{
//ill bind data to checkboxes
}
else if (q.Question_Type == 12) // indicate its fill in the blanks question
{
for (int j = 0; j < que.Length; j++)
{
if (que[j] == '#')
{
count++;
string res = "<input type = 'text' runat = 'server' id ='TxtBoxFillUp" + count + "'/>";
htm = htm.Append(res);
}
else
{
htm = htm.Append(que[j]);
}
}
}
}
Any help will be greatly appreciated, thanks in advance.
Adding control in the way you do it won't create control as asp.net creates it. You do have to create controls as usual .net object.
TextBox myNewTextBox = new TextBox() {};
// Set all initial values to it
And add this cotrol to placeholder or panel, whatever you use. Keep in mind that asp.net page events fire even if you use update panel, so in order to maintain state and events of newly created controls you have take care of creating such controls long before page's Load event fires. Here is my answer to another simialiar question.
Seeing the requirements you have:
1.) You need to use JavaScript. Since the ASP.NET will not recreate controls which are dynamically added. Dynamically added controls need to be recreated after every postback. This is the reason why your TextBoxes are Lost after every postback.
2.) You can write JavaScript code to Hide and show the textboxes for blank texts since at every button click you can call Client side functions using: OnClientClick() property of buttons.
3.) Also to Get the TextBoxes using ID property, add them in Markup( .aspx ) portion itself.
I will be starting a project soon at my company and the client would like to have the option in the portal to add textboxes or checkboxes as an administrator,,, so for instance initially I may have something like
Name [textBox]
Phone [textBox]
So the client would like to log in as an admin and be able to add
Name [textBox]
Phone [textBox]
Receive Brochure [checkBox] //added by client.
Forget about the portal and the admin part.. what I would like to know is what would be the best way to design this (the user to be able to add elements)
Any ideas would be much appreciated
Regards
You could create an additional aspx-form in which the User (or the Admin) is able to define and create his/her own forms, you supply the Variable names and they choose to add the controls, save it in a specific scheme in the Database, e.g.
UserForm:
UserID FormID
Form:
FormID FormName
FormElement:
FormID VariableName ControlType Index
Of course this could also be done by an administrator and be visible by everyone.
To view the specific forms you could add yet another aspx-page containing the following code:
protected void Page_Load(object sender, EventArgs e)
{
//you saved the FormName or ID to Session when you accessed it
string formName = Session["FormName"].ToString();
//this handles getting the elements for this Form from DB
List<FormElement> elementList = FormElement.GetForForm(formName);
this.renderForm(elementList);
}
private void renderForm(List<FormElement> eList)
{
foreach(FormElement fe in eList)
{
//Labels left, Controls right, of course this is just a design decision
if(fe.Index%2==1)
{
Label lbl = new Label();
lbl.Text = fe.Variable;
lbl.ID = fe.ControlType + fe.Variable;
divLeft.Controls.Add(lbl);
}
else
{
dynamic ctrl = null;
switch (fe.ControlType)
{
case "TextBox":
ctrl = new TextBox();
break;
case "CheckBox":
ctrl = new CheckBox();
break;
default:
break;
}
ctrl.ID = fe.ControlType + fe.Variable;
divRight.Controls.Add(ctrl);
}
}
}
Later on after the User hitting submit you'd be able to receive the values entered into those Controls by accessing divRight.FindControl(fe.ControlType + fe.Variable) since that should be unique per Form.
This approach assumes you're using .NET 4.0 (because of dynamic), but of course you can do this just fine without it, it'll just be more code.
Please let me know if this is what you searched for or if it was helpful.
Thanks,
Dennis
From what I have done in the past where I had to create a dynamic survey based on a client needs. I had a database that contained the following tables:
Survey - stores list of client surveys.
Controls - listed the type of controls that would be needed. For example, textbox, checkbox etc.
Survey Controls - links all the controls required for a survey.
User values - stores the values entered in a controll based on the survey used.
I then added some logic to dynamically create the controls based on a survey selected by reading the values from my database.
Here is what I am trying to do. I have a TreeView server side control (asp.net 2.0) and I need the user to be able to add nodes to it, then after all the nodes desired are added, the data should be saved to the database.
Here are some things I would like to pay attention to:
1) I don't want to save the tree data each time the new node is added, but rather keep the data in session until the user decides to save the entire tree. The question here is: can I bind the tree to ArrayList object and keep that object in session (rather than keeping the whole tree in session)? Then each time the node is added I will have to rebind the tree to the ArrayList rather than database.
2) I wish to minimize ViewState, any tips? What works best: compressing viewstate or keeping it all on the server at all times?
Thanks!
Use TreeNodeCollection as your internal array to hold in either ViewState or Session. Here's a rough mock-up of an approach you can use; far from perfect, but should set you on the right track.
TreeView tv = new TreeView();
// Button click event for 'Add Node' button
protected void AddNode(object sender, EventArgs e)
{
if (SaveNodeToDb(txtNewNode.Text, txtNavUrl.Text))
{
// Store user input details for new node in Session
Nodes.Add(new TreeNode() { Text = txtNewNode.Text, NavigateUrl = txtNavUrl.Text });
// Clear and re-add
tv.Nodes.Clear();
foreach (TreeNode n in Nodes)
tv.Nodes.Add(n);
}
}
public bool SaveNodeToDb(string name, string url)
{
// DB save action here.
}
public TreeNodeCollection Nodes
{
get
{
if (Session["UserNodes"] ! = null)
return (TreeNodeCollection) Session["UserNodes"];
else
return new TreeNodeCollection();
}
set
{
Session["UserNodes"] = value;
}
}