Custom Control Event not firing inside a user control - asp.net

I implement a custom control that handle post back event:
namespace CalendarControls
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class CalendarPostback : WebControl, IPostBackEventHandler
{
public delegate void CalendarPostBackHandler(object sender, CalendarPostbackEventArgs e);
public event CalendarPostBackHandler CalendarPostBack;
public CalendarPostback()
{
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
string[] values = eventArgument.Split('|');
CalendarPostbackEventArgs args = new CalendarPostbackEventArgs();
args.EventType = (eEventType)Convert.ToInt32(values[0]);
if (args.EventType == eEventType.Insert)
args.EventDate = Convert.ToDateTime(values[1]);
else
args.EventId = Convert.ToInt32(values[1]);
if (CalendarPostBack != null)
CalendarPostBack(this, args);
}
#endregion
}
public class CalendarPostbackEventArgs : EventArgs
{
public CalendarPostbackEventArgs()
{
}
public eEventType EventType
{
get;
set;
}
public DateTime EventDate
{
get;
set;
}
public int? EventId
{
get;
set;
}
}
}
and I use this custom control in a usercontrol ,and call it on a button click inside my usercontrol with following javascript code:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.ClientID %>', eventArguments);
}
and my html code in usercontrol:
<input type="button" value="Insert" onclick="CallPostBack('1|2014/06/12')" />
<CalendarControls:CalendarPostback ID="ctl1" runat="server" ClientIDMode="Static" OnCalendarPostBack="ctl1_CalendarPostBack" />
but when I click on my button, page postback occur but ctl1_CalendarPostBack event not fired. also I must to say that I add user control directly to aspx page (not dynamically) and my aspx page have a master page.
now I have two question:
what's wrong with my code? how to solve this issue?
if I want to add my custom control to an update panel and I want to have an async post back, what I must do?
thank you,
best regards

I found problem! when we use master page ,client id and unique id of control is different and we must to use unique id instead of client id:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.UniqueID %>', eventArguments);
}

Related

ASP.NET Dynamic Data: Find Data Control of DynamicControl from FormView using Column Name

Greetings StackOverflow,
TL;DR
In a field template control's OnLoad method how can I find the Data Control of other fields in a FormView by property or column name.
END TL;DR.
I'm trying to add a some logic to the Boolean_Edit field template so that if the property bound to it has a new attribute I made the template will inject JavaScript. The JavaScript is intended to disable all of the data controls of the column/property names listed in the attribute's ControlledFieldNames property.
This is sort of confusing so I'll share some code.
Here is the attribute class I made for this:
/// <summary>
/// Attribute used to insert javascript into an ASP.NET web page that uses Dynamic Controls so that if the field's value changes it disables (or enables)
/// other web controls on the page which correspond to the other bound property names.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public sealed class InputRestrictorFieldAttribute : Attribute
{
public Boolean TargetEnabledState { get; set; }
public String[] ControlledFieldNames { get; set; }
public InputRestrictorFieldAttribute(Boolean targetEnabledState, params String[] controlledFieldNames)
{
this.TargetEnabledState = targetEnabledState;
this.ControlledFieldNames = controlledFieldNames;
}
}
So I might have a property in some scaffolded class like so:
[ScaffoledTable(true)]
public class Person
{
/* Other properties... */
[InputRestrictorFieldAttribute(false, new String[]
{
"StreetAddress",
"City",
"State",
"Zip"
})]
public Boolean AddressUnknown { get; set; }
public String SteetAddress { get; set; }
public String City { get; set; }
public String State { get; set; }
public String Zip { get; set; }
/* some more code */
}
Now in the Boolean_Edit.ascx.cs file I am trying to check if the currently scaffold property has the InputRestrictorFieldAttribute and if so inject JavaScript onto the page such that when the AddressUnknown CheckBox control is check is disabled the TextBox controls for StreetAddress, City, State, and Zip.
Below is what I have tried most recently.
protected override void OnLoad(EventArgs e)
{
var attributes = this.Column.Attributes;
foreach (Attribute attr in attributes)
{
if (attr is InputRestrictorFieldAttribute)
{
InputRestrictorFieldAttribute restrictor = (InputRestrictorFieldAttribute)attr;
String restrictorScriptFunctionName = String.Format(RESTRICTOR_SCRIPT_FUNCTION_NAME, ClientID);
String restrictorScript = String.Format(RESTRICTOR_SCRIPT_TEMPLATE_ONCLICK,
restrictorScriptFunctionName,
restrictor.BoundFieldNames.Aggregate("", (aggr, item) =>
{
var bc = this.NamingContainer.BindingContainer;
var ctrl = bc.FindFieldTemplate(item);
return aggr + String.Format(RESTRICTOR_SCRIPT_TEMPLATE_ELEMENT, ctrl.ClientID);
}));
Page.ClientScript.RegisterStartupScript(Page.GetType(), "restrictorScript_" + ClientID, restrictorScript, true);
CheckBox1.Attributes.Add("onchange", restrictorScriptFunctionName + "(this);");
}
}
base.OnLoad(e);
}
Now I know doing things like getting the this.NamingContainer.BindingContainer many not (or probably wont) work in other pages but for now (in the context of the Insert.aspx page template) works. this.NamingContainer.BindingContainer is the FormView1 control of the Insert.aspx page. But everything I've tried so far to get the various data dontrols or field templates, or dynamic controls by their property name it always returns null or throws an exception.
Lastly, the aggregate method is just concatenating pieces of JavaScript together so that all of the controls are deactivated using just one JavaScript function. The contents of those script are not important to this question.
there is an extension method called FindFieldTemplate see see it here

ASP.NET customized asp:label view state

I created a new class for a project. The below is a very slightly simplified version.
public class CustomLabel : Label
{
public string ItemId { get; set; }
protected override void Render(HtmlTextWriter writer)
{
if (!Page.IsPostBack)
LoadText();
base.Render(writer);
}
protected void LoadText()
{
this.Text = "This is a test";
}
}
The problem I'm having is that the Text property is not lasting through postbacks. Even if I manually enable viewstate though the tag on the ascx page. Can the custom label tag not have viewstate? I would hate to have to load the text on every page load unnecessarily.
Move LoadText(); method call to OnPreRender method

asp.net store object class in viewstate (or other ideas)

I've build a class like this:
private class TestResults
{
public bool IsAdmitted { get; set; }
public bool IsDuplicate { get; set; }
public bool IsVerified { get; set; }
}
The values of this class are set at postback by clicking a radiobutton list. Problem however is I don't know how to save this values across multiple postbacks. I thought of using viewstate but I'm not quite sure how to do it with this class.
Maybe I'm missing some important thing here.
Hope someone can point me in the right direction
thanks for your time!
Kind regards,
Mark
Just sticking this class in viewstate is pretty simple:
ViewState["SomeUniqueKey"] = myTestResults;
var testResults = (TestResults)ViewState["SomeUniqueKey"];
Your class will need to be marked with the [Serializable] attribute though.
try using the Session cache instead
var testResults = new TestResults();
//set values
Session["TestResults"] = testResults;
Retrieving them later on:
var testResults = Session["TestResults"] as TestResults;
if (testResults != null)
{
//use it
}
You can use
Session.Add("TestResults", Your_Test_Result_Object)
Session Object Explanation
If you don't need this value on other pages or in other places throughout the app, you can use viewstate.
Use the Page.ViewState object bag to store it:
public partial class Page1 : Page {
protected void button1_click(object sender, EventArgs e) {
ViewState["myObject"] = testResultsObject;
}
}
You could also wrap the access to it in a property on the page:
public partial class Page1 : Page {
public TestResults TestResults {
get{ return ViewState["TestResults"] as TestResults; }
set{ ViewState["TestResults"] = value; }
}
}

ASP.NET Templated Control

I'm attempting to build a templated control. You'll see that as part of the Field section, I'd like to be able to define controls as children. When I attempt to compile I'm receiving the error message "MyTemplateControl.Field' does not have a public property named 'Button'". Does anyone know how to accomplish what I'm trying to do?
Below you'll find an example XHTML markup, and below that my control implementation.
I've editted my example to hopefully clarify what I'm looking for. Thanks everyone for the MSDN links. I've been through those already.
What I'm trying to build is a data entry control that will auto format a table for me. We do a lot of data entry webforms, and I'd like to ease the implementation time.
<cc1:MyForm ID="MyForm1" runat="server">
<ViewTemplate>
<cc1:Field Question="What is your name?">
<asp:Label ID="myLabel" runat="server" />
</cc1:Field>
</ViewTemplate>
<EditTemplate>
<cc1:Field Question="What is your name?">
<asp:Textbox ID="myTextbox" runat="server" />
</cc1:Field>
</EditTemplate>
</cc1:MyForm>
public class MyForm : WebControl, INamingContainer
{
private FieldCollection _fieldCollection;
private FieldCollection _field2Collection;
public FieldCollection ViewTemplate
{
get
{
if (_fieldCollection == null)
{
_fieldCollection = new FieldCollection();
}
return _fieldCollection;
}
}
public FieldCollection EditTemplate
{
get
{
if (_field2Collection == null)
{
_field2Collection = new FieldCollection();
}
return _field2Collection;
}
}
}
public class FieldCollection : CollectionBase
{
.
.
.
}
[ParseChildren(false)]
public class Field
{
.
.
.
}
There's something strange in your implementation. It's difficult to understand what you'd like to do, either to build a templated control, or a control on which you can add a list of child controls.
For the templated approach you'd have to do something like this:
public class MyForm : WebControl, INamingContainer
{
private TemplateOwner templateOwner{ get; set; }
private ITemplate _Content;
public ITemplate Content
{
get
{
return this._Content;
}
set
{
_Content = value;
}
}
protected override void CreateChildControls()
{
base.Controls.Clear();
templateOwner = new TemplateOwner();
this.Content.InstantiateIn(templateOwner);
this.Controls.Add(templateOwner);
}
...
}
[ToolboxItem(false)]
public class TemplateOwner : WebControl{
public TemplateOwner():base(HtmlTextWriterTag.Div)
{
}
}
The usage would then look like
<cc1:MyForm ID="MyForm1" runat="server">
<Content>
<!-- Place whatever HTML, ASP.net controls etc you like -->
</Content>
</cc1:MyForm>
You still have to add the appropriate annotations to configure the behavior of the designer. I just wrote this down quickly to give you an idea.
GridView also doesn't allow such manipulation,
Instead use MyForm1.FindControl("mybutton")
Also I have notice your template is not derived from ITemplate interface. As usual ASP.Net also uses System.Web.UI.Control as base class for this impl.
I used the following code:
public partial class SmallFramedControl : UserControl, INamingContainer
{
private TemplateOwner templateOwner { get; set; }
private ITemplate _Content;
public ITemplate Content
{
get
{
return this._Content;
}
set
{
_Content = value;
}
}
protected override void CreateChildControls()
{
//base.Controls.Clear();
templateOwner = new TemplateOwner();
this.Content.InstantiateIn(templateOwner);
plchAdd.Controls.Add(templateOwner);
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
[ToolboxItem(false)]
public class TemplateOwner : WebControl
{
public TemplateOwner()
: base(HtmlTextWriterTag.Div)
{
}
}
and ascx page look like:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="SmallFramedControl.ascx.cs"
Inherits="OtPortalNewDesign.UserControls.SmallFramedControl" %>
this will be top of frame
<asp:PlaceHolder ID="plchAdd" runat="server"></asp:PlaceHolder>
this will be bottom of frame

Set Property Value on Master Page from Content Page

I need to pass data to a variable in my master page each time a page is loaded.
I have a string[] of RequiredRoles that I set on each content page defining what roles are required to access that page.
On my master page, I have a method that takes this array, and checks to see if the current user is in one or more of those roles.
How would I go about managing this? I basically want each page to have a String[] RequiredRoles defined, and the master page will load this on each call and check to see if the users are in those roles.
Add page directive to your child page:
<%# MasterType VirtualPath="~/MasterPage.master" %>
Then add property to your master page:
public string Section { get; set; }
You can access this property like this:
Master.Section = "blog";
Typecast Page.Master to your master page so that you are doing something like:
((MyMasterPageType)Page.Master).Roles = "blah blah";
Create a property in your master page and you access it from content page:
Master page:
public partial class BasePage : System.Web.UI.MasterPage
{
private string[] _RequiredRoles = null;
public string[] RequiredRoles
{
get { return _RequiredRoles; }
set { _RequiredRoles = value; }
}
}
Content Page:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load()
{
Master.RequiredRoles = new string[] { /*set appropriate roles*/ };
}
}
I'd go by creating a base class for all the content pages, something like:
public abstract class BasePage : Page
{
protected abstract string[] RequiredRoles { get; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// display the required roles in a master page
if (this.Master != null) {
// value-assignment
}
}
}
And then I make every page inherits from BasePage, and each defining a RequiredRoles
public partial class _Default : BasePage
{
protected override string[] RequiredRoles
{
get { return new[] { "Admin", "Moderator" }; }
}
}
This has the advantage of cleanliness and DRY-ing the OnLoad handler code. And every page which inherits from BasePage are required to define a "RequiredRoles" or else it won't compile.
CType(Master.FindControl("lblName"), Label).Text = txtId.Text
CType(Master.FindControl("pnlLoginned"), Panel).Visible = True

Resources