Where in the page lifecycle can I safely load/remove dynamic controls?
I'm working with dynamic fields in ASP.NET due to a very specifc and rigid end-user requirement that would take 2 hours just to explain. Suffice it to say, I can't make the requirement go away.
Anyway, I have a working solution in place; no problems with controls loading, rendering or maintaining their ViewState. This is what my OnLoad looks like:
public void override OnLoad(EventArgs e){
//don't need to check IsPostback, we have to load the controls on every POST
FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
}
In order to implement some biz logic around which dynamic fields are required, disabled or optional, I need to get the posted values (i.e. the ViewState) of my dynamic controls before I can actually add them to the page control hierarchy.
It's sort of a chicken/egg problem I suppose. ASP.NET won't automagically associate ViewState with the proper dynamic control until I've added them all to the page. On the other hand, I can't add these controls to the page until my service layer has applied biz rules that hinge on their current values. I tried to get around this rather unpleasant problem by writing this bit of pseud开发者_StackOverflow社区o-code :
public void override OnLoad(EventArgs e){
FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
if (IsPostBack){
PushControlValuesIntoForm(initialFormDefinition);
var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
ReBuildControls(updatedFormDefinition); //remove controls and re-add them
}
}
Unfortunately, when you clear a control and re-add it, the ViewState is lost, even if the control type and ControlID are exactly the same, so this solution is a bust. Any reasonable ideas on how to accomplish what I'm after are welcome!
One way could be to load your controls and then decide if you need form definition to be be updated and if yes then re-initiate page life cycle again. See the below sample code:
public void override OnLoad(EventArgs e){
var updatedFormDef = Context.Items["UpdatedDef"] as FormDefinition;
if (null != updatedFormDef)
{
// Updated form def, rebuild controls
BuildControls(updatedFormDef);
}
else
{
// load initial form def
var initialFormDefinition = ServiceLayer.GetFormDefinition(id);
BuildControls(initialFormDefinition);
// check whether we need to update form def
if (IsPostBack){
PushControlValuesIntoForm(initialFormDefinition);
var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
if (null != updatedFormDefinition)
{
// we have to update UI, transfer to self
Context.Items["UpdatedDef"] = updatedFormDefinition;
try
{
Server.Transfer(this.Request.RawUrl, true);
}
catch(ThreadAbortException)
{
// Do nothing
}
}
}
}
精彩评论