WPF binding issue while using NavigationCommands.BrowseBack property - c#

I wonder why this behavior happening in my page.
I have a page (say 'x') which has set of text boxes which are defined inside a container say a stack panel and the data is bounded with this stack panel using datacontext in c#.
now when I am navigating to another page and again moving back to that page (page 'x') (URI Navigation) the data binding will happen and the fields will be filled buy the object's data as the getter method of the object's property will get called ,but by pressing back button (NavigationCommands.BrowseBack) there will be no data binding happens in the page. no field will take the date as the getters method of properties of the object will not called in this case!!
I don't want to do it in back end by reffering to each text box and assigning values to them.
any one having the same issue or solution for that please share.

You might try to update your bindings manually. For example you could write the following code as an extension to "BenCr's" answer in this post Is there a way to refresh all bindings in WPF?
var temp = yourStackPanel.DataContext;
yourStackPanel.DataContext = null;
yourStackPanel.DataContext = temp;

Related

The text of a textbox in a dynamic control is not set on post back due to UniqueID change

As the title suggests, we are having issues getting the correct text value of a Textbox after a post back.
Context:
The Textbox is called textbox_registration
The Textbox is in a dynamically loaded control.
The dynamic control is recreated every post back and has its data set in the OnInit event.
The dynamic controls are within a PlaceHolder inside an UpdatePanel.
It is expected that the value posted in the form will then be present in the Text property of the Textbox. The first form submission is fine, then it gets weird. The UniqueID of textbox_registration changes in every subsequent submission, breaking the expected value stored in the Text property. The following is an example of the UniqueIDs of the Textbox.
ctl00$CollapsableSidebar$panel_editAsset$ctl01$textbox_registration
ctl00$CollapsableSidebar$panel_editAsset$ctl02$textbox_registration
My theory is that when the dynamic control it loaded in init again it avoids a collision with the previous instance of the Textbox by changing the generated UniqueID, then when the second post back occurs the ID has to be different, and thus corrupting the ViewState initialisation between the init and load methods.
This is very irritating, because looking in the Request.Form collection I can see the correctly posted value.
How can I retrieve the posted value for textbox_registration.Text?
Edit 1:
Just to clarify textbox_registration is a normal static ASP Textbox within a UserControl that we have loaded dynamically.
Edit 2:
To outline the scenario, the source code has been stripped down to the following files:
Item Page, a page to display items.
Edit Pane, a custom UserControl on the Item Page that is used to load the dynamic controls.
Dynamic Control, an example of a dynamic item editing control loaded into the Edit Pane.
IEditItemPanel, an interface that the edit controls must implement.
Try setting ClientIDMode property when you create your TextBox control
textbox_registration.ClientIDMode = ClientIDMode.Static;
Then when you want to retrieve the text
var textBox = (TextBox)this.Form.FindControl("textbox_registration");
var textBoxText = textBox.Text;
After investigating the issue, it was a logical error causing the issue.
Because the edit control was loaded dynamically it was important that the control was loaded for post backs by the end of OnInit or up to OnLoad as long as the item was loaded in the control before Controls.Add() was called.
With this knowledge, the OnInit event was investigated closely in the dynamic control. It was being called twice on the post backs! A logic error! This caused the controls to be created twice and the posted form values corresponded to the controls created in the first OnInit call. Therefore, the second OnInit call generated different UniqueIDs for the controls. When the ViewState was restored the controls did not exist.
The solution was to make sure the control is created properly every post back like the first time it is created. The first time didn't make a duplicate control, so neither should the second!
Turns out a look back at the 'Dynamic Controls Basics 101' was needed.
This link 'Dynamic Controls Made Easy in ASP.Net' finally made the solution click into focus.

In ASP.NET, how to store controls in a Dictionary

I am storing ASP.NET Controls (Tables, Buttons, TextBoxes) in a Dictionary in a webform application, so that they can be accessed directly from user controls, instead of having to do a recursive search for them from other user controls. When they are added to the dictionary, I can verify that the visible control on the .ascx control is identical to the object in the Dictionary: X == Y returns true. But later on, when I want to do something like changing a background color, or disabling a button, X == Y returns false. A change that I make to the object in the Dictionary (which is declared as static) is not reflected in the visible GUI control.
How do I correct this?
(it's difficult to give you a helpful answer without seeing any code, and without understanding what you're trying to achieve, but ...)
Whenever a Postback is made, a new instance of the page and all its controls is created. Therefore the control instances stored in your dictionary no longer match with the control instances on the current page instance. They are still the instances created when the page was requested for the first time.
But in any case, storing control instances in a static dictionary is a very bad idea (e.g. think about what happens when multiple users call your page in parallel).
Please explain what you want to achieve and why you think your dictionary is necessary. It will then probably be easier to help you.
The dictionary stores information about each control. However, the controls that the UI displays are separate. Every time you make a change to one element in the dictionary, you have to set the actual UI components to = their corresponding dictionary element. So
Dictionary["textBoxExampleKey"].Text = "blah";
won't change the actual textbox. To update the textbox to match the value in the dictionary, do`
textBoxExample.Text = Dictionary["textBoxExampleKey"].Text;
I recommend making a method that updates the entire UI to match the dictionary for the sake of simplicity. So this method would be something like
private void UpdateUI()
{
textBoxExample.Text = Dictionary["textBoxExampleKey"].Text;
labelExample.Text = Dictionary["labelExampleKey"].Text;
listBoxExample.DataSource = Dictionary["listBoxExampleKey"].DataSource;
Refresh();
}
The "Refresh()" method reloads your UI so that all changes are made visible, which could also be part of your problem.
TL;DR: Update your actual controls, refresh your UI.

C# ASP.NET - Dynamic MenuItems in a user control are randomly being duplicated outside of control creation

EDIT: I needed to skip control creation during post back -- see my answer below.
I'm working on a very basic front end to a simple tool and I wanted to present some data in a much more sorted and useful way, instead of making one huge wall of text. I found this tutorial on building a simple tabbed interface using MultiView, but have run into a bizarre problem. I can't use Ajax tabs because of legal hissy fits over 3rd party software.
My webpage is a basic ASP.NET page with a user control plopped in the middle of it. In this control's ascx file, I defined the Menu (empty) and the MultiView (also empty) so that I can dynamically populate the tabs with content driven from an external file.
When the default page's OnInitComplete function is called, I call through to the user control to load the data file, then build out the tabs and the view content based on the loaded data. I tried doing this from PageLoad, PreInit, and CreateChildControls, but I kept getting an errors saying that I was setting the the MultiView's active view index at an invalid time (and also that there were 0 views despite the fact I just added a bunch of them):
ActiveViewIndex is being set to '0'. It must be smaller than the
current number of View controls '0'. For dynamically added views, make
sure they are added before or in Page_PreInit event.
But OnInitComplete appears to work just fine, so I went with that.
I iterate over the loaded data (multiple lists of strings), and for each list, I add a MenuItem with the list's title to the Menu and a View to the MultiView. The View is populated with a table->row->cell as in the above tutorial. In the cell, I add the list title and a CheckBoxList data bound to the list of strings.
So far so good, but when I click on a tab (or one of the checkboxes, etc) and there is a postback or something like that (the screen flashes as the site redraws itself), there is now a duplicate set of MenuItems immediately after the original. Each time I click on a tab or checkbox, another set of menu items are added.
I clear the MenuItem's Items list prior to building the controls and I verify that the controls hierarchy is structurally as expected after the control construction. Yet when one of my callbacks is called, my MenuItem list magically has some items added to it. None of my other controls appear affected at all. As a hack, I can remove the duplicates manually in my menu's OnMenuItemClick event, but I'd have to do the same in any of the callbacks I receive. Obviously I'd rather prevent this from happening. This has me stumped and I haven't been able to find anything online about it. Why would one set of controls have some content duplicated, yet every other control maintain its state correctly? My code is really simple so there isn't a way to add additional menu items without also adding the views. Anyway, there are a correct number of items prior to clicking on the tab/checkbox, an additional set immediately following in the callback.
This is my first time using ASP.NET, so I'm learning as I go. :) Thanks!
My problem was that I was not testing for postback before creating the controls. The code below is working for me.
In my user control's code behind:
protected void OnInitComplete( EventArgs e )
{
if( !Page.IsPostBack )
{
CreateMyControls();
}
}

Is there a quick way of adding an event to many controls at once in WPF?

I have 400+ textboxes on a page. The page is meant to be an exact replica of a paper form. The user is going to edit all of the fields and then save the data to the DB. The data is being pulled down into a DataTable from a SQL DB.
I'm planning on saving the data via the same DataTable or just via a bulk update. Not 100% on that. But, I need to get access to that data. And maybe I'm not doing this next best part the best and if I'm not, I'd appreciate it if I was informed of a better way.
When the DataTable gets the data, I assign each field into the appropriate control. Below is an example of how the data is being added.
foreach (DataRow CDR in ClaimDataTable.Rows){
if (CDR["BoxNumber"].ToString() == "1.1")
this.Box1_1.Text = CDR["DataValue"].ToString();
if (CDR["BoxNumber"].ToString() == "1.2")
this.Box1_2.Text = CDR["DataValue"].ToString();
if (CDR["BoxNumber"].ToString() == "1.3")
this.Box1_3.Text = CDR["DataValue"].ToString();
I wrote some code to automatically create that code. So I didn't manually write all 400+ lines.
What I was thinking, was that I could add a LostFocus event to each TextBox. Then when the control loses focus, I would create a class with a box name and the box value. Add that to a list and when they're ready to save, just loop through the list and do the bulk update with the BoxNumber and the box data.
Would that be feasible? Or is there a better method?
Thanks!
Look into event routing.
You should not create and access individual text-boxes but let the framework create them via datatemplating a collection, your above code is ze horror.
When the DataTable gets the data, I assign each field into the
appropriate control.
WPF is data binding and one does not generally load controls as you mentioned. Why is the code not binding to each control to a property which adheres to INotifyPropertyChanged?
Have the page's DataContext (DC) point to an instantiated class which adheres to InotifyPropertyChanged interface. The setting of the DC in that fashion will allow all controls on the page to use its datacontext by default.
In the class to be instantiated for the DC create a member property which calls PropertyChanged when the value is set using the INotifyPropertyChanged system.
Bind each TextBox Text property to that property on the class.
Then each control which needs that value will display it automatically after it has been set such as in this example.
<TextBlock Name="tbHeader"
Text="{Binding CDRData}" />
Then one only has to write the value to the property named CDRData once and all textboxes bound get the value.

ASP.NET - Dynamic Control Values & Postback

I'm trying to persist the contents of a textbox through a postback, and I've exhausted all of my effort but can't get it working right.
What should happen is:
User selects a radiobutton
Depending which button was
selection, a usercontrol is loaded
to specify some data and a viewstate
to say which enum type it's
equivalent to.
When they click
save, if the UserControl is just a
textbox input - the simplest), the
contents are read and saved, then
saved to the database with the
format(the radiobutton choice) so
they can be deserialized again
later.
The page posts back, and
the value and format are read from
the database, then the right control
is loaded.
The problem is - the first time the page posts back, it works. Every other postback it resets to the default value of the textbox.
I have a very similar setup elsewhere, so I'm thinking it might be a minor thing I'd never think of. There's a lot of code, so it might be easier to talk about what to do (load the dynamic control, populate the values etc) rather than how to do it.
There was actually a bug in my original code which meant it would never have in the way I was using the modified version. Apparently state is restored in Page_Load, so any controls need to be initialized by to have their values restored.
Creating the control in Page_PreLoad, then populating it after Page_Load solved the problem.

Categories

Resources