Creating, Using and Discarding Temporary Value not working - c#

I am trying to assign a ViewState value in my application with a SelectedIndexChanged function. Once it's assigned the postback will use the value to change some data and then set the value to zero but I can't seem to get it to work correctly. The controls are all created dynamically on Page_Load.
Page Load
protected void Page_Load(object sender, EventArgs e)
{
CreateAttributeControls();
TempProductVariantId = 0;
}
Create Attribute Controls
public void CreateAttributeControls()
{
...
var ddlArtistArtworks = new DropDownList();
ddlArtistArtworks.ID = "ddlArtistArtworksTest";
divAttribute.Controls.Add(ddlArtistArtworks);
ddlArtistArtworks.Items.Clear();
ddlArtistArtworks.SelectedIndexChanged += new EventHandler(ArtistArtwork_SelectedIndexChange);
ddlArtistArtworks.AutoPostBack = true;
...
}
ArtistArtwork_SelectedIndexChange
protected void ArtistArtwork_SelectedIndexChange(object sender, EventArgs e)
{
DropDownList ddl = sender as DropDownList;
TempProductVariantId = int.Parse(ddl.SelectedValue);
}
TempProductVariantId ViewState Save
public int TempProductVariantId
{
get
{
if (ViewState["TempProductVariantId"] == null)
return 0;
else
return (int)ViewState["TempProductVariantId"];
}
set
{
ViewState["TempProductVariantId"] = value;
}
}
When I load the page everything is fine. I change the DropDownList's value, It posts back, and the value is not set. Change it again the value is set and continues to change as I change the value of the DropDownList.
Any guidance on this would be greatly appreciated.
Note: I have tried changing when CreateAttributeControls() is called. In OnPreRender for example. I was given this to understand the lifecycle of the page Life Cycle

That's because you are essentially recreating the dropdown on every postback..
try this
public void CreateAttributeControls()
{
...
DropDownList ddlArtistArtworks;
if (!IsPostBack)
{
ddlArtistArtworks = new DropDownList();
ddlArtistArtworks.ID = "ddlArtistArtworksTest";
divAttribute.Controls.Add(ddlArtistArtworks);
ddlArtistArtworks.Items.Clear();
ddlArtistArtworks.AutoPostBack = true;
}
else
{
ddlArtistArtworks = (DropDownLise)divAttribute.FindControl("ddlArtistArtworksTest");
}
ddlArtistArtworks.SelectedIndexChanged += new EventHandler(ArtistArtwork_SelectedIndexChange);
...
}
For dynamically added controls, the event handler has to be linked up everytime so that has to be done outside the if-block, unconditionally.

Related

Saving values from User Control

I have an aspx page. On pageLoad a call a method that loads a user control
protected void Page_Load(object sender, EventArgs e)
{
LoadUC();
}
This loads the user control onto the page (into a placeholder) passing a few generic values.
private void LoadUC()
{
ucTS ctrl = (ucTS)Page.LoadControl(_ucTSPath);
ctrl.ParentId = 0;
ctrl.addNew = false;
phFG.Controls.Add(ctrl);
}
The user control (which contains a repeater) loads the initial placeholder as well as another placeholder on the initial page:
protected void Page_Load(object sender, EventArgs e)
{
LoadItems();
}
private void LoadBOMItems()
{
List<Item> dtItem;
if (ParentId == 0)
{
if (ViewState["ItemFG"] == null)
{
dtItem = //Gets list of items
}
else
{
dtItem = (List<Item>)ViewState["ItemFG"];
}
ViewState["ItemFG"] = dtItem;
}
else
{
if (ViewState["Items" + ParentId] == null)
{
dtItem = //get list of items
}
else
{
dtItem = (List<Item>)ViewState["Items" + ParentId];
}
ViewState["Items" + ParentId] = dtItem;
}
if (dtItem.Count > 0)
rptTSItem.DataSource = dtItem;
rptTSItem.DataBind();
}
}
in the binding, I bind the repeater, but I am also adding more of the same user control.
The problem comes when I click add a new item to the repeater. The initial click, everything saves fine and a new row is added. The second click the user control is not found on the initial page and so the save method is not fires. The 3rd click, everything is fine, the 4th, the user control is not found. This keeps happening. Why is my usercontrol not always found? I have tried doing a postback check in multiple places, but that doesn't seem to work.
I am still not 100% sure why the event would fire properly every OTHER time as opposed to just the first time, but the solution was simply adding an ID to the user control.
private void LoadUC()
{
ucTS ctrl = (ucTS)Page.LoadControl(_ucTSPath);
ctrl.ParentId = 0;
ctrl.addNew = false;
ctrl.ID = "someID"
phFG.Controls.Add(ctrl);
}
and whenever I re-added the user control from within the user control, I pass the same ID.

How To Set A RadGrid's Page Size Programmatically Without Triggering A PageSizeChanged Event

I'm using a Telerik RadGrid with custom paging. My problem is that when I set the page size manually, the PageSizeChanged event gets fired and throws my code into an infinite loop. As a hack, I created a boolean that is set when the PageSizeChanged event gets fired. How do I set the page size on a RadGrid control without triggering the PageSizeChanged event?
private bool PageSizeChanged
{
get { return Convert.ToBoolean(ViewState["PageSizeChanged"]); }
set { ViewState["PageSizeChanged"] = value; }
}
protected void RadGrid1_PageSizeChanged(object sender, GridPageSizeChangedEventArgs e)
{
if (!PageSizeChanged)
{
PageSizeChanged = true;
RadGrid1.PageSize = e.NewPageSize;
}
PageSizeChanged = false;
RadGrid1.Rebind();
}
UPDATE: I have a solution that I like now. I ended up removing the event handler from the invocation list, setting the page size and then adding the event back to the invocation list.
protected void RadGrid1_PageSizeChanged(object sender, GridPageSizeChangedEventArgs e)
{
RadGrid1.PageSizeChanged -= RadGrid1_PageSizeChanged;
RadGrid1.PageIndex = 0;
RadGrid1.PageSize = e.NewPageSize;
RadGrid1.Rebind();
RadGrid1.PageSizeChanged += RadGrid1_PageSizeChanged;
}
try this-
protected void RadGrid1_PageSizeChanged(object source, GridPageSizeChangedEventArgs e)
{
RadGrid1.PageSizeChanged-=new GridPageSizeChangedEventHandler(RadGrid1_PageSizeChanged);
RadGrid1.PageSize = e.NewPageSize;
RadGrid1.PageSizeChanged += new GridPageSizeChangedEventHandler(RadGrid1_PageSizeChanged);
RebindGrid();
}
Remove the RadGrid1_PageSizeChanged, and assing the page size as -
RadGrid1.MasterTableView.PageSize = CustomerPageSize;

How can I load the Same ASP Grid View with different conditions?

I have a DDL and a ASP .net Grid view in my aspx page. I have two methods getALLProgram and getProgramBy name, both are working fine. My problem is: when the page is loaded for the first time, I want to call the getAllprogram method, after that if a User selects a program from DDL I want my getprogramByname method to be called.
How here is my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindProgramDDL();
BindGrid();
}
//BindProgramDDL();
}
protected void BindGrid()
{
string strProgramCode = DDLProgram.SelectedIndex.ToString();
List<FormGridEntity> gridEntities = new List<FormGridEntity>();
GridForResult.DataSource = gridEntities;
GridForResult.DataBind();
//throw new NotImplementedException();
}
protected void BindProgramDDL()
{
List<CcProgramEntity> programEntities = FormSaleSubmit_BAO.GetAllPrograms();
DDLProgram.DataSource = programEntities;
DDLProgram.DataTextField = "Shortname";
DDLProgram.DataValueField = "Id";
DDLProgram.DataBind();
string programCode = programEntities[DDLProgram.SelectedIndex].Code;
}
protected void OnDDLProgramChanged(object sender, EventArgs e)
{
List<CcProgramEntity> programEntities = FormSaleSubmit_BAO.GetAllPrograms();
string programCode = programEntities[DDLProgram.SelectedIndex].Code;
}
The Code is incomplete. i am still working on it. But I not getting the logic How will I make this happen that I have told you here. I hope I made my question clearly, if it confusing, please let me know what else I should provide here.
You should check in your BindGrid if any program has been selected or not and route the call as per that. For example,
protected void BindGrid()
{
...
if (DDLProgram.SelectedIndex >= 0)
{
// program selected
var programCode = DDLProgram.SelectedValue;
data = GetProgramByName(programCode);
}
else
{
// get all programs
data = GetAllPrograms();
}
// bind data with grid
}
You can either call BindGrid in page_load unconditionally (i.e. in post-back scenarios also) or invoke it on your DDL change.
how about writing getProgramByname on a selected index changed event of a drop down list and getALLProgram on page load event ?
I hope, I was clear on what your doubt and the above mentioned suggestion did helped.
Just change these 2 things
protected void BindGrid()
{
List<FormGridEntity> gridEntities = (DDLProgram.SelectedIndex==-1)
?FormSaleSubmit_BAO.GetAllPrograms()
:FormSaleSubmit_BAO.GetProgramByName(DDLProgram.SelectedValue);
GridForResult.DataSource = gridEntities;
GridForResult.DataBind();
}
protected void OnDDLProgramChanged(object sender, EventArgs e)
{
BindGrid();
}

How to fire DropDownListBox SelectIndexChange event programmatically?

[edit]
calling the follows directly is not possible in my code:
void control_Changed(object sender, EventArgs e)
This function is loop through a Collection of DropDownListBox, and each DropDownListBox has different Select_Change function. Also they are not in the same page, they collection of DropDownListBox is come from different user control of the page.
I saw a lot of solution are simply calling the function that the event should trigger..
But this will not be working on my case.
I have a code that will mapping the data to a collection of dropdownlistbox and select the proper dropdownlistbox item for each dropdownlistbox.
So, is kind of like this:
foreach (Control aControl in aControlCollection){
if (aControl.GetType() == typeof(RadComboBox))
{
bool FoundItem = false;
RadComboBox aComboBox = (aControl as RadComboBox);
foreach (RadComboBoxItem aComboItem in aComboBox.Items)
{
Debug.WriteLine("aComboItem " + aComboItem.Text + " Value" + aComboItem.Value);
if (aComboItem.Value.ToLower() == _dataObject.ToString().ToLower())
{
//aComboBox.SelectedIndex = aComboBox.Items.IndexOf(aComboItem);
aComboItem.Selected = true;
FoundItem = true;
~~~FIRE EVENT HERE~~~~~
//break;
}
else {
aComboItem.Selected = false;
}
}
if (!FoundItem)
{
RadComboBoxItem aComboItem = new RadComboBoxItem();
aComboItem.Value = _dataObject.ToString();
aComboItem.Text = _dataObject.ToString();
aComboBox.Items.Add(aComboItem);
aComboBox.SelectedIndex = aComboBox.Items.IndexOf(aComboItem);
}
}
}
}
Normally in the page, when user select the a first dropdownbox, the 2nd dropdownbox that follows will generate the proper dropdownlist item according to the first dropdownbox (from the first dropdownbox selectindexchange event).
So I wonder if there is anyway I can fire the DropDownListBox programmatically?
Just to make it even more clear, the above function is call by iterates all DropDownListBox on the page, so they can be link into different function.
Combobox_SelectedItem(null, null);
You can forge any arguments you desire into the parameters, if needed.
If you were to use the traditional void control_Changed(object sender, EventArgs e) code...
if (aComboItem.Value.ToLower() == _dataObject.ToString().ToLower())
{
//aComboBox.SelectedIndex = aComboBox.Items.IndexOf(aComboItem);
aComboItem.Selected = true;
FoundItem = true;
control_Changed(aComboItem, new EventArgs());
}
void control_Changed(object sender, EventArgs e) {
// your code here
}

ASP.NET putting dynamic controls on page in reverse messes up events

I have this weird problem when putting textboxes on the page in reverse. The whole event system is messed up. Changing one textbox fires TextChange on all textboxes. I can fix this by putting the controls in a list first and then call add while iterating trough the list in reverse. But i just want to know why this fails. Heres some code (.net 2.0)
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
InitFields();
}
private void InitFields()
{
int nrFields;
//We have a static textbox called nrElements, this determines the number
//of fields to initialize
if (int.TryParse(nrElements.Text, out nrFields))
{
//Put all the dynamic fields on the screen in reverse order
foreach(Control t in GetDynamicFields(nrFields))
{
//Calling Controls.Add works fine
//Calling Controls.AddAt messes up the events
//Try changing different textboxes
plhFields.Controls.AddAt(0, t);
}
}
}
private IEnumerable<Control> GetDynamicFields(int nrFields)
{
for (int i = 0; i < nrFields; i++)
{
TextBox txtBox = new TextBox();
txtBox.ID = string.Format("dynTextBox{0}", i.ToString());
txtBox.AutoPostBack = true;
txtBox.TextChanged += t_TextChanged;
yield return txtBox;
}
}
private void t_TextChanged(object sender, EventArgs e)
{
TextBox txtBox = sender as TextBox;
if (txtBox != null)
txtBox.Text = txtBox.Text + "Changed ";
}
}
Try calling InitFields() on the Page_PreInit event rather than Page_Load.
Or an alternative would be to override the CreateChildControls() method (MSDN Article), if you use CreateChildControls() you'll need to call EnsureChildControls() on the Page_Load method to make sure the CreateChildControls() method has been called before you try to access any controls which have been created within that method.
Always put dynamic controls in OnInit event. Then viewstate serializer/deserializer will work. And you have to add controls on every request, not just in !IsPostBack.

Categories

Resources