DateTimeControl Custom OnDateChange event not firing in SharePoint - asp.net

The custom event for a DateTimeControl is not firing. Instead the CreateChildControls() is firing, every-time I change the date on Calendar.
namespace myn
{
class StopTimeFieldControl : BaseFieldControl
{
protected DateTimeControl dateTime;
public override object Value
{
get
{
EnsureChildControls();
if (dateTime == null)
{
return string.Empty;
}
return dateTime.SelectedDate;
}
set
{
EnsureChildControls();
dateTime.SelectedDate = Convert.ToDateTime(this.ItemFieldValue);
}
}
protected override string DefaultTemplateName
{
get
{
return "StopTimeFieldControl";
}
}
public override void Validate()
{
if (ControlMode == SPControlMode.Display || !IsValid)
{
//this.ViewState["StopTimeFieldControl"] = Value.ToString();
return;
}
base.Validate();
if (dateTime.IsDateEmpty)
{
this.ErrorMessage = " Du måste ange ett värde för det här obligatoriska fältet.";
IsValid = false;
return;
}
try
{
StartTimeFieldControl child = (StartTimeFieldControl)FindControlRecursive(this.Page, "startDateTime").Parent;
if (dateTime.SelectedDate < Convert.ToDateTime(child.Value))
{
this.ErrorMessage = " Du måste ange ett värde som är senare än startdatum.";
IsValid = false;
return;
}
}
catch (Exception e)
{
PortalLog.LogString("## Exception Occurred: Fail when trying to catch startDateTime ** {0} || {1}", e.Message, e.StackTrace);
}
this.Page.Session["startDateTime"] = Value;
}
protected override void CreateChildControls()
{
if (Field == null) return;
base.CreateChildControls();
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display)
return;
if (ControlMode == SPControlMode.New || ControlMode == SPControlMode.Edit)
{
dateTime = new DateTimeControl();
dateTime.CssClassTextBox = "ms-long";
dateTime.TimeZoneID = 1053;
dateTime.LocaleId = 1053;
dateTime.ID = "stopDateTime";
dateTime.AutoPostBack = true;
this.dateTime.DateChanged += new EventHandler(dateTime_DateChanged);
Controls.Add(dateTime);
}
//ChildControlsCreated = true;
}
void dateTime_DateChanged(object sender, EventArgs e)
{
string hi = "hej";
}
public static Control FindControlRecursive(Control Root, string Id)
{
if (Root.ID == Id)
return Root;
foreach (Control Ctl in Root.Controls)
{
Control FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
}
}

Try to create your DateTimeControl control in PreInit or Init phase and not in CreateChildControls. Possible reason of such behaviour - your control is created too late, when page life cycle passed through postback event handling.

CreateChildControls() is firing,
every-time I change the date on
Calendar
But is the event handler being bound every time?
In most cases i dont create controls in if statements, things tend to not get wired up correctly.
Try just making the control invisible instead.
dateTime = new DateTimeControl();
if (ControlMode == SPControlMode.New || ControlMode == SPControlMode.Edit)
{
datetime.Visible = false;

Related

Is this the best/correct way to use the DevExpress ASPxGridView to edit a List<T>?

Would someone who knows DeveExpess ASPxGridView take a look at this.
Is this the best/correct way to use the grid to edit a List?
I have an object of Type ItemModel and the code below is used to allow an ASP.NET Web Site user to do CRUD operations on list of ItemModels.
My problem is that it seems too complex and I suspect I am not taking good advantage of the Grid.
For simplicity, I have left the Database Access Code that will load and save the list of ItemModels.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
BindGrid();
}
protected void OnRowInserting(object sender, ASPxDataInsertingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = 0;
if (itemModels .Count > 0)
{
lineID = itemModels[itemModels.Count - 1].LineID + 1;
}
ItemModel itemModel = new ItemModel()
{
, Code = e.NewValues["Code"] == null ? string.Empty : e.NewValues["Code"].ToString()
, Name = e.NewValues["Name"] == null ? string.Empty : e.NewValues["Name"].ToString()
, DateCreated = DateTime.Now
, DateUpdated = DateTime.Now
};
itemModels.Add(itemModel);
CachedModels = itemModels;
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
protected void OnRowUpdating(object sender, ASPxDataUpdatingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = Convert.ToInt32(e.Keys[0].ToString());
ItemModel itemModel = null;
foreach (ItemModel model in itemModels)
{
if (model.LineID == lineID)
{
itemModel = model;
break;
}
}
if (itemModel != null)
{
itemModel.Code = e.NewValues["Code"] == null ? string.Empty : e.NewValues["Code"].ToString();
itemModel.Name = e.NewValues["Name"] == null ? string.Empty : e.NewValues["Name"].ToString();
containerItemModel.DateUpdated = DateTime.Now;
itemModels[lineID] = itemModel;
CachedModels = itemModels;
}
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
protected void OnRowDeleting(object sender, ASPxDataDeletingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = Convert.ToInt32(e.Keys[0].ToString());
ItemModel itemModel = null;
foreach (ItemModel model in itemModels)
{
if (model.LineID == lineID)
{
itemModel = model;
break;
}
}
if (itemModel != null)
{
itemModels.Remove(itemModel);
CachedModels = itemModels;
}
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
private void BindGrid()
{
grdItems.DataSource = CachedModels;
grdItems.DataBind();
}
private IList<ItemModel> CachedModels
{
get
{
List<ItemModel> models= (List<ItemModel>)Session["ItemModels"];
if (models == null)
{
models= new List<ItemModel>();
Session["ItemModels"] = models;
}
return models;
}
set
{
Session["ItemModels"] = value;
}
}
I believe your current code is quite correct.
Here is the suggested way from DX:
ASPxGridView - How to implement CRUD operations with a custom data source

how to use updatepanel with AsyncRefresh event

I developing an asp.net web application.In that application i am using asyncRefresh event
for continuously updating the value.If i am using updatepanel the asyncRefresh event won't get the focus.Without updatepanel evet getting the focus.I want to use asynRefresh event with updatepanel.Any one Please help for this problem.
Thanks&Regards
Lijo Thomas
protected void Page_Load(object sender, EventArgs e)
{
object et = Request.Form["__EVENTTARGET"] as object;
if (et != null)
{
Control c = Page.FindControl(et.ToString());
if (c != null)
{
ScriptManager.GetCurrent(this).SetFocus(GetUniqueIdSmart(c));
}
}
}
protected static string GetUniqueIdSmart(Control control)
{
string id = control.UniqueID.Replace('$', '_');
string controlIDSuffix = "";
RadioButtonList rbl = control as RadioButtonList;
if (rbl != null)
{
controlIDSuffix = "_0";
int t = 0;
foreach (ListItem li in rbl.Items)
{
if (li.Selected)
{
controlIDSuffix = "_" + t.ToString();
break;
}
t++;
}
}
else if (control is CheckBoxList)
{
controlIDSuffix = "_0";
}
id += controlIDSuffix;
return id;
}

ASP.NET: How to persist Page State accross Pages?

I need a way to save and load the Page State in a persistent manner (Session). The Project i need this for is an Intranet Web Application which has several Configuration Pages and some of them need a Confirmation if they are about to be saved. The Confirmation Page has to be a seperate Page. The use of JavaScript is not possible due to limitations i am bound to. This is what i could come up with so far:
ConfirmationRequest:
[Serializable]
public class ConfirmationRequest
{
private Uri _url;
public Uri Url
{ get { return _url; } }
private byte[] _data;
public byte[] Data
{ get { return _data; } }
public ConfirmationRequest(Uri url, byte[] data)
{
_url = url;
_data = data;
}
}
ConfirmationResponse:
[Serializable]
public class ConfirmationResponse
{
private ConfirmationRequest _request;
public ConfirmationRequest Request
{ get { return _request; } }
private ConfirmationResult _result = ConfirmationResult.None;
public ConfirmationResult Result
{ get { return _result; } }
public ConfirmationResponse(ConfirmationRequest request, ConfirmationResult result)
{
_request = request;
_result = result;
}
}
public enum ConfirmationResult { Denied = -1, None = 0, Granted = 1 }
Confirmation.aspx:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.UrlReferrer != null)
{
string key = "Confirmation:" + Request.UrlReferrer.PathAndQuery;
if (Session[key] != null)
{
ConfirmationRequest confirmationRequest = Session[key] as ConfirmationRequest;
if (confirmationRequest != null)
{
Session[key] = new ConfirmationResponse(confirmationRequest, ConfirmationResult.Granted);
Response.Redirect(confirmationRequest.Url.PathAndQuery, false);
}
}
}
}
PageToConfirm.aspx:
private bool _confirmationRequired = false;
protected void btnSave_Click(object sender, EventArgs e)
{
_confirmationRequired = true;
Response.Redirect("Confirmation.aspx", false);
}
protected override void SavePageStateToPersistenceMedium(object state)
{
if (_confirmationRequired)
{
using (MemoryStream stream = new MemoryStream())
{
LosFormatter formatter = new LosFormatter();
formatter.Serialize(stream, state);
stream.Flush();
Session["Confirmation:" + Request.UrlReferrer.PathAndQuery] = new ConfirmationRequest(Request.UrlReferrer, stream.ToArray());
}
}
base.SavePageStateToPersistenceMedium(state);
}
I can't seem to find a way to load the Page State after being redirected from the Confirmation.aspx to the PageToConfirm.aspx, can anyone help me out on this one?
If you mean view state, try using Server.Transfer instead of Response.Redirect.
If you set the preserveForm parameter
to true, the target page will be able
to access the view state of the
previous page by using the
PreviousPage property.
use this code this works fine form me
public class BasePage
{
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
//Save the last search and if there is no new search parameter
//Load the old viewstate
try
{ //Define name of the pages for u wanted to maintain page state.
List<string> pageList = new List<string> { "Page1", "Page2"
};
bool IsPageAvailbleInList = false;
foreach (string page in pageList)
{
if (this.Title.Equals(page))
{
IsPageAvailbleInList = true;
break;
}
}
if (!IsPostBack && Session[this + "State"] != null)
{
if (IsPageAvailbleInList)
{
NameValueCollection formValues = (NameValueCollection)Session[this + "State"];
String[] keysArray = formValues.AllKeys;
if (keysArray.Length > 0)
{
for (int i = 0; i < keysArray.Length; i++)
{
Control currentControl = new Control();
currentControl = Page.FindControl(keysArray[i]);
if (currentControl != null)
{
if (currentControl.GetType() == typeof(System.Web.UI.WebControls.TextBox))
((TextBox)currentControl).Text = formValues[keysArray[i]];
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.DropDownList))
((DropDownList)currentControl).SelectedValue = formValues[keysArray[i]].Trim();
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.CheckBox))
{
if (formValues[keysArray[i]].Equals("on"))
((CheckBox)currentControl).Checked = true;
}
}
}
}
}
}
if (Page.IsPostBack && IsPageAvailbleInList)
{
Session[this + "State"] = Request.Form;
}
}
catch (Exception ex)
{
LogHelper.PrintError(string.Format("Error occured while loading {0}", this), ex);
Master.ShowMessageBox(enMessageType.Error, ErrorMessage.GENERIC_MESSAGE);
}
}
}

Saving State Dynamic UserControls...Help!

I have page with a LinkButton on it that when clicked, I'd like to add a Usercontrol to the page. I need to be able to add/remove as many controls as the user would like. The Usercontrol consists of three dropdownlists. The first dropdownlist has it's auotpostback property set to true and hooks up the OnSelectedIndexChanged event that when fired will load the remaining two dropdownlists with the appropriate values.
My problem is that no matter where I put the code in the host page, the usercontrol is not being loaded properly. I know I have to recreate the usercontrols on every postback and I've created a method that is being executed in the hosting pages OnPreInit method. I'm still getting the following error:
The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
Here is my code:
Thank you!!!!
bool createAgain = false;
IList<FilterOptionsCollectionView> OptionControls
{
get
{
if (SessionManager.Current["controls"] != null)
return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"];
else
SessionManager.Current["controls"] = new List<FilterOptionsCollectionView>();
return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"];
}
set
{
SessionManager.Current["controls"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
Master.Page.Title = Title;
LoadViewControls(Master.MainContent, Master.SideBar, Master.ToolBarContainer);
}
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
System.Web.UI.MasterPage m = Master;
Control control = GetPostBackControl(this);
if ((control != null && control.ClientID ==
(lbAddAndCondtion.ClientID) || createAgain))
{
createAgain = true;
CreateUserControl(control.ID);
}
}
protected void AddAndConditionClicked(object o, EventArgs e)
{
var control = LoadControl("~/Views/FilterOptionsCollectionView.ascx");
OptionControls.Add((FilterOptionsCollectionView)control);
control.ID = "options" + OptionControls.Count.ToString();
phConditions.Controls.Add(control);
}
public event EventHandler<Insight.Presenters.PageViewArg> OnLoadData;
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
protected Control GetPostBackControl(System.Web.UI.Page page)
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = FindControlRecursive(page, ctrlname.Split('$')[2]);
}
else
{
string ctrlStr = String.Empty;
Control c = null;
foreach (string ctl in Page.Request.Form)
{
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = page.FindControl(ctrlStr);
}
else
{
c = page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.CheckBox ||
c is System.Web.UI.WebControls.CheckBoxList)
{
control = c;
break;
}
}
}
return control;
}
protected void CreateUserControl(string controlID)
{
try
{
if (createAgain && phConditions != null)
{
if (OptionControls.Count > 0)
{
phConditions.Controls.Clear();
foreach (var c in OptionControls)
{
phConditions.Controls.Add(c);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
Here is the usercontrol's code:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="FilterOptionsCollectionView.ascx.cs" Inherits="Insight.Website.Views.FilterOptionsCollectionView" %>
namespace Insight.Website.Views
{
[ViewStateModeById]
public partial class FilterOptionsCollectionView : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void OnInit(EventArgs e)
{
LoadColumns();
ddlColumns.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(ColumnsSelectedIndexChanged);
base.OnInit(e);
}
protected void ColumnsSelectedIndexChanged(object o, EventArgs e)
{
LoadCriteria();
}
public void LoadColumns()
{
ddlColumns.DataSource = User.GetItemSearchProperties();
ddlColumns.DataTextField = "SearchColumn";
ddlColumns.DataValueField = "CriteriaSearchControlType";
ddlColumns.DataBind();
LoadCriteria();
}
private void LoadCriteria()
{
var controlType = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].CriteriaSearchControlType;
var ops = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].ValidOperators;
ddlOperators.DataSource = ops;
ddlOperators.DataTextField = "key";
ddlOperators.DataValueField = "value";
ddlOperators.DataBind();
switch (controlType)
{
case ResourceStrings.ViewFilter_ControlTypes_DDL:
criteriaDDL.Visible = true;
criteriaText.Visible = false;
var crit = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].SearchCriteria;
ddlCriteria.DataSource = crit;
ddlCriteria.DataBind();
break;
case ResourceStrings.ViewFilter_ControlTypes_Text:
criteriaDDL.Visible = false;
criteriaText.Visible = true;
break;
}
}
public event EventHandler OnColumnChanged;
public ISearchCriterion FilterOptionsValues { get; set; }
}
}
I figured it out. Here is my solution:
I modified the GetPostBackControl to look for not only the linkbutton that inserts the user control, but for controls that contain the id of child controls of the inserted user control(as to capture the OnSelectedIndexChanged that gets fired from inside my user control).
protected Control GetPostBackControl(System.Web.UI.Page page)
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
//if it contains options then it's a control inside my usercontrol
if (ctrlname.Split('$')[2].Contains("options"))
{
var c = new Control();
c.ID = ctrlname;
return c;
}
else
{
control = FindControlRecursive(page, ctrlname.Split('$')[2]);
}
}
else
{
string ctrlStr = String.Empty;
Control c = null;
foreach (string ctl in Page.Request.Form)
{
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = page.FindControl(ctrlStr);
}
else
{
c = page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.CheckBox ||
c is System.Web.UI.WebControls.CheckBoxList)
{
control = c;
break;
}
}
}
return control;
}
Then I modify the OnPreInit event to look for controls with an id of the linkbutton or an id that contains "options" :
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
System.Web.UI.MasterPage m = Master;
Control control = GetPostBackControl(this);
if (control != null)
{
if ((control.ClientID == (lbAddAndCondtion.ClientID) || createAgain) || control.ID.Contains("options"))
{
createAgain = true;
CreateUserControl(control.ID);
}
}
}
The critical fix was in the CreateUserControl method. In my original code I was trying to directly load the user control from my generic list that was stored in Session. I changed that to actually create a new instance of the user control, assign that new instance an id that matches the one stored in Session, and then add it to the placeholder:
protected void CreateUserControl(string controlID)
{
try
{
if (createAgain && phConditions != null)
{
if (OptionControls.Count > 0)
{
phConditions.Controls.Clear();
foreach (var c in OptionControls)
{
FilterOptionsCollectionView foc = new FilterOptionsCollectionView();
foc = Page.LoadControl("~/Views/FilterOptionsCollectionView.ascx") as FilterOptionsCollectionView;
foc.ID = c.ID;
phConditions.Controls.Add(foc);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
The only thing I changed in the user control was moving the method that loads my drop down lists's and wiring up the OnSelectedIndexChanged event into the OnInit event. Now I can dynamically load as many instances of the user control I want and all of the event's inside the user control fire correctly and state is persisted across postbacks!!
Hope this helps someone else!!

ASP custom controls don't fire correct events

I'm building a library of custom controls. My controls are inherited from CompositeControl.
Depending on the user's answer I have to insert more custom control. I have a PlaceHolder (_ph) passed in from the client code. I insert my controls into that PlaceHolder.
My problem is the control I inserted in the event handler does not fire its event, but it fires the parent event. For example, if I have an EddDropDown A, and the user picks an answer, I have to create EddDropDown B and C in edd_SelectedIndexChanged. When I pick an answer for B, it fires SelectedIndexChanged for A instead of B.
I think it has something to do with entering the page cycle late. I don't know how to fix it. Please help. Really appreciate any assistant.
Thanks in advance.
this is an example of my controls:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommerceBank.DueDiligence.ServiceProxies.Internal.Edd;
using System.Collections.Specialized;
using System.Runtime.Serialization;
namespace CommerceBank.DueDiligence.ClientFacade.WebForms
{
public class EddDropDownListArgs : EventArgs
{
private int _iQuestionID;
string _sAnswer = string.Empty;
private DueDiligenceProfile _customerProfile;
public EddDropDownListArgs(int iQuestionID, string sAnswer,DueDiligenceProfile customer)
{
_iQuestionID = iQuestionID;
_sAnswer = sAnswer;
_customerProfile = customer;
}
public int QuestionID
{
get
{
return _iQuestionID;
}
set
{
_iQuestionID = value;
}
}
public string Answer
{
get
{
return _sAnswer;
}
set
{
_sAnswer = value;
}
}
public DueDiligenceProfile customerProfile
{
get
{
return _customerProfile;
}
set
{
_customerProfile = value;
}
}
}
public delegate void EddDropDownSelectedIndexChangedHandler(object sender, EddDropDownListArgs ce);
[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("ID"),
ToolboxData("<{0}:EddDropDown runat=\"server\"> </{0}:EddDropDown>"),
Serializable
]
public class EddDropDown : CompositeControl, IChannelControl,ISerializable, IPostBackEventHandler, IPostBackDataHandler
{
[Serializable]
struct EddDropDownData
{
public int _iQuestionID;
public String _sQuestion;
//public AnswerOption[] _PossibleAnswers;
public String _sAnswer;
//public DueDiligenceProfile _customerProfile;
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("This is EddCheckBox"),
Localizable(true)
]
private int _iQuestionID=-1;
private String _sQuestion = string.Empty;
private AnswerOption[] _PossibleAnswers;
private String _sAnswer = string.Empty;
private DueDiligenceProfile _customerProfile;
private EddDropDownData _data = new EddDropDownData();
Label _lQuestion = null;
DropDownList _ddl = null;
#region implement custom events
public event EddDropDownSelectedIndexChangedHandler SelectedIndexChanged;
protected virtual void OnSelectedIndexChanged(EddDropDownListArgs eddEvent)
{
if (SelectedIndexChanged != null)
{
System.Diagnostics.Trace.WriteLine("OnSelectedIndexChanged. QuestionID:"
+ eddEvent.QuestionID
+ " Answer: "
+ eddEvent.Answer);
SelectedIndexChanged(this, eddEvent);
}
}
#endregion
#region IPostBackEventHandler_implementation
// Define the method of IPostBackEventHandler that raises change events.
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
System.Diagnostics.Trace.WriteLine("in RaisePostBackEvent" + eventArgument);
OnSelectedIndexChanged(new EddDropDownListArgs(EDDQuestionID(), EDDAnswerValue(), _customerProfile));
}
#endregion
#region IPostBackDataHandler_implementation
bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
{
//System.Diagnostics.Trace.WriteLine("in LoadPostData");
//int i = int.Parse(postCollection["SelectedIndex"]);
//string s = postCollection["SelectedValue"];
//if (SelectedIndex >= 0)
// Page.RegisterRequiresRaiseEvent(this);
//return false;
return true;
}
void IPostBackDataHandler.RaisePostDataChangedEvent()
{
System.Diagnostics.Trace.WriteLine("in RaisePostDataChangedEvent");
}
#endregion
#region ISerializable_implementation
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("ControlType", GetType().Name);
info.AddValue("ControlID", ID);
info.AddValue("QuestionID", _iQuestionID);
info.AddValue("Question", Question);
info.AddValue("Answer", EDDAnswerValue());
info.AddValue("PossibleAnswerCount", _PossibleAnswers.Length);
for (int i=0; i < _PossibleAnswers.Length; i++)
{
info.AddValue("a" + i.ToString(), _PossibleAnswers[i]);
}
}
#endregion
#region IChannel_implementation
public int EDDQuestionID()
{
return QuestionID;
}
public string EDDAnswerValue()
{
EnsureChildControls();
for (int i = 0; i < Controls.Count; i++)
{
if (Controls[i].ID == "ans" + QuestionID)
{
_sAnswer = ((DropDownList)Controls[i]).SelectedValue;
_data._sAnswer = ((DropDownList)Controls[i]).SelectedValue;
ViewState["SelectedIndex"] = ((DropDownList)Controls[i]).SelectedIndex;
return ((DropDownList)Controls[i]).SelectedValue;
}
}
return null;
}
#endregion
#region Overriden properties
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return base.Controls;
}
}
#endregion
#region Properties
public int QuestionID
{
get
{
_iQuestionID = (int)ViewState["QuestionID"];
return _iQuestionID;
}
set
{
ViewState["QuestionID"] = value;
_iQuestionID = value;
}
}
public string Question
{
get
{
_sQuestion = (string)ViewState["Question"];
return _sQuestion;
}
set
{
ViewState["Question"] = value;
_sQuestion = value;
}
}
public string Answer
{
get
{
return _sAnswer;
}
set
{
_sAnswer = value;
}
}
public int SelectedIndex
{
get {
EnsureChildControls();
if (ViewState["SelectedIndex"] != null)
_ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
else
_ddl.SelectedIndex = 0;
return _ddl.SelectedIndex;
}
set {
EnsureChildControls();
ViewState["SelectedIndex"] = value;
_ddl.SelectedIndex = value;
}
}
public string SelectedValue
{
get
{
EnsureChildControls();
_ddl.SelectedValue =(string)ViewState["SelectedValue"];
return _ddl.SelectedValue;
}
set
{
EnsureChildControls();
ViewState["SelectedValue"] = value;
_ddl.SelectedValue = value;
}
}
#endregion
public EddDropDown(int iQuestionID
, string sQuestion
, DueDiligenceProfile cust
, AnswerOption[] sPossibleAnswers
)
{
System.Diagnostics.Trace.WriteLine("Add EddDropDown. QuestionID :"
+ iQuestionID.ToString()
+ sQuestion);
QuestionID = iQuestionID;
Question = sQuestion;
_data._iQuestionID = iQuestionID;
_data._sQuestion = sQuestion;
_PossibleAnswers = sPossibleAnswers;
_customerProfile = cust;
ID = iQuestionID.ToString()+GetCustomerID();
}
public EddDropDown(SerializationInfo info, StreamingContext context)
{
string sControlType = info.GetString("ControlType");
ID = info.GetString("ControlID");
QuestionID = info.GetInt32("QuestionID");
Question = info.GetString("Question");
string sAnswer = info.GetString("Answer");
int iAnswerCount = info.GetInt32("PossibleAnswerCount");
List<AnswerOption> answerOptions = new List<AnswerOption>();
for (int i = 0; i < iAnswerCount; i++)
{
Type t = typeof(AnswerOption);
AnswerOption ao = (AnswerOption)info.GetValue("a" + i.ToString(), t);
answerOptions.Add(ao);
}
_PossibleAnswers = answerOptions.ToArray();
}
protected override object SaveViewState()
{
ViewState["SelectedIndex"] = _ddl.SelectedIndex;
return base.SaveViewState();
}
protected override void LoadViewState(object savedState)
{
//if (ViewState["SelectedIndex"] != null)
// _ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
//else
// _ddl.SelectedIndex = 0;
if (savedState != null)
{
Pair mystate = (Pair)savedState;
ArrayList al =(ArrayList)mystate.First;
for (int i = 0; i < al.Count;i++ )
{
if (al[i].GetType().Name == "IndexedString")
{
if (((IndexedString)al[i]).Value == "SelectedIndex")
{
ViewState["SelectedIndex"] = al[i + 1].ToString();
System.Diagnostics.Trace.WriteLine(al[i + 1].ToString());
}
}
}
}
base.LoadViewState(savedState);
}
//need this to get the post back
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Name, this.ID);
writer.AddAttribute(HtmlTextWriterAttribute.Onchange,
Page.ClientScript.GetPostBackEventReference(this, ID));
//writer.AddAttribute(HtmlTextWriterAttribute.Onchange,
// Page.ClientScript.GetPostBackEventReference(_ddl, _ddl.ID));
base.AddAttributesToRender(writer);
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Page.RegisterRequiresPostBack(this);//must register postback in OnPreRender
}
protected override void Render(HtmlTextWriter writer)
{
//Ensures that this control is nested in a server form
if (Page != null)
{
Page.VerifyRenderingInServerForm(this);
}
base.Render(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
RenderChildren(writer);
}
protected override void CreateChildControls()
{
Controls.Clear();
_lQuestion = new Label();
_lQuestion.ID = "quest" + QuestionID;
_lQuestion.Text = Question;
_ddl = new DropDownList();
_ddl.ID = "ans" + QuestionID;
//add "select one"
ListItem liSelectOne = new ListItem("Please select one");
_ddl.Items.Add(liSelectOne);
for (int i = 0; i < _PossibleAnswers.Count(); i++)
{
AnswerOption a = _PossibleAnswers[i];
ListItem li = new ListItem(a.Value.ToString());
_ddl.Items.Add(li);
//if (a.ChildQuestions == null)//default it to the answer that don't have some children
// ddl.Items[i].Selected = true;
}
if (_sAnswer != string.Empty)
_ddl.SelectedValue = _sAnswer;
_ddl.AutoPostBack = true;//must have
_ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged);
if (ViewState["SelectedIndex"] != null)
_ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
//else
// _ddl.SelectedIndex = 0;
Page.RegisterRequiresPostBack(_ddl);
Page.RegisterRequiresControlState(_ddl);
Controls.Add(new LiteralControl("<br>"));
Controls.Add(_lQuestion);
Controls.Add(new LiteralControl("<br>"));
Controls.Add(_ddl);
ChildControlsCreated = true;
//ClearChildViewState();
}
private string GetCustomerID()
{
if (_customerProfile.Customer.PermanentId >0)
return _customerProfile.Customer.PermanentId.ToString();
else if (_customerProfile.Customer.RcifId != null && _customerProfile.Customer.RcifId != "")
return _customerProfile.Customer.RcifId;
else
return _customerProfile.Customer.TaxId.ToString();
}
//to do: delete
//void edd_SelectedIndexChanged(object sender, EddDropDownListArgs ea)
//{
// System.Diagnostics.Trace.WriteLine("get here");
//}
void ddl_SelectedIndexChanged(object sender, EventArgs e)
{
Control c = (Control)sender;
System.Diagnostics.Trace.WriteLine("ddl_SelectedIndexChanged "
+ c.GetType().Name);
OnSelectedIndexChanged(new EddDropDownListArgs(EDDQuestionID(), EDDAnswerValue(),_customerProfile));
}
protected override void RenderChildren(HtmlTextWriter output)
{
if (HasControls())
{
for (int i = 0; i < Controls.Count; i++)
{
Controls[i].RenderControl(output);
}
}
}
}
}
This is the code that create the controls:
public EddDropDown GetDropDown(DueDiligenceProfile cust, Question quest)
{
Control c = null;
if (HasControl(quest.Id.ToString(), "EddDropDown", ref c))
return (EddDropDown)c;
string sQuestion = null;
AnswerOption[] sPossAnswers;
sPossAnswers = FindPossibleAnswers(cust.Questions, quest.Id, ref sQuestion);
if (sPossAnswers == null)
throw (new Exception("failed to get possible answers"));
EddDropDown edd = new EddDropDown(quest.Id,
sQuestion,
cust,
sPossAnswers
);
edd.ID = quest.Id.ToString();
edd.SelectedIndexChanged += new EddDropDownSelectedIndexChangedHandler(edd_SelectedIndexChanged);
_data._EDDControls.Add(edd);
int iParentQuestionID = FindParentQuestionID(cust.Questions, quest.Id, ref sQuestion);
int iControlIdx = GetIndexOf(iParentQuestionID, _ph.Controls);
if (iControlIdx >-1)
_ph.Controls.AddAt(iControlIdx + 1, edd);
else
_ph.Controls.Add(edd);
//build children questions if they have result
if (quest.Results.Length >0)
{
foreach (Result r in quest.Results)
{
edd.SelectedValue = r.Value;
foreach (AnswerOption ao in quest.AnswerOptions)
{
if (r.Value == ao.Value)
{
if (ao.ChildQuestions == null)
continue;
foreach (Question q in ao.ChildQuestions)
{
EddDropDown e = GetDropDown(cust, q);
e.BackColor = System.Drawing.Color.CadetBlue;
}
}
}
}
}
return edd;
}
void edd_SelectedIndexChanged(object sender, EddDropDownListArgs ea)
{
System.Diagnostics.Trace.WriteLine("EddQuestionare--edd_SelectedIndexChanged. QuestionID:"
+ ea.QuestionID
+ " Answer: "
+ ea.Answer);
//Control parentControl = null;
//if (sender.GetType().Name == "EddDropDown")
//{
// parentControl = (Control)sender;
//}
//Control c = (Control)sender;
//while (c.GetType().Name != "PlaceHolder")
// c = c.Parent;
string sQuestion = null;
AnswerOption[] ansOptions = FindPossibleAnswers(ea.customerProfile.Questions
, ea.QuestionID
, ref sQuestion);
foreach (AnswerOption ao in ansOptions)
{
if (ao.Value == ea.Answer)//found answer
{
if (ao.ChildQuestions == null)
break;
//create sub questions
for (int i = 0; i < ao.ChildQuestions.Length; i++)//and there are subquestions
{
_ph.Controls.Add(new LiteralControl(" "));
if (ao.ChildQuestions[i].AnswerOptions.Length > 2)
{
EddDropDown subQues = GetDropDown(ea.customerProfile
, ao.ChildQuestions[i]);
subQues.BackColor = System.Drawing.Color.Aqua;
}
else if (ao.ChildQuestions[i].AnswerOptions.Length == 2)
{
EddRadioButtonList erb = GetRadioButtonList(ea.customerProfile
, ao.ChildQuestions[i].Id);
erb.BackColor = System.Drawing.Color.BlueViolet;
}
else
{
EddTextArea eta = GetTextArea(ea.customerProfile
, ao.ChildQuestions[i].Id);
eta.BackColor = System.Drawing.Color.Bisque;
}
}
break;
}
}
//DisplayControls();
//Serialize();
}
There are a few things that I haven't cleaned out, but you get the idea.
The postback events might not be getting to your control.
In the page that is using your controls, try overriding the RaisePostbackEvent and call the RaisePostBackEvents for each control:
protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
this.yourcustomcontrol1.RaisePostBackEvent(sourceControl, eventArgument);
this.yourcustomcontrol2.RaisePostBackEvent(sourceControl, eventArgument);
base.RaisePostBackEvent(sourceControl, eventArgument);
}

Resources