Validating Form Fields in an ITemplate - c#

I have a custom control which includes a property of the following definition:
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Template {
get { return template; }
set { template = value; }
}
The control overrides CreateChildControls(), and adds several HtmlGenericControls and an asp:Panel control.
The actual actual implementation of the control looks something like this:
<user:Frame runat="server">
<Template>
<asp:Literal runat="server" ID="SomeControl" Text="SomeValue" />
</Template>
</user:Frame>
While the page renders as intended, it has a number of consequences of varying severity, including:
Controls enclosed within the Template cannot be referenced directly, and FindControl is required. This is fine.
I've been unable to use validation controls on them.
Is there a better way to design my custom control? Or perhaps just a way to get validation working?

By default the framework assumes that you may have more than one template in a control, like say in a Repeater. In your case you have to tell it that you intend to have a single template by using the TemplateInstance property. E.g.
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate Template {
get { return template; }
set { template = value; }
}
This will allow you to reference the templated controls directly, and should fix your validation problems as well.

One way to get validation to work in this case is to add the validation controls programatically. For example:
var c = parentControl.FindControl("id");
parentControl.Controls.AddAt(
parentControl.Controls.IndexOf(c) + 1,
new RequiredFieldValidator() { ControlToValidate = c.D });

Related

Access parent DIV of user-control (ascx) from its code behind

From within the code-behind of an ASP .NET web user-control (ascx) I need to get access (at runtime) to its parent, a div element. The aim is simple as to modify the visibility of the mentioned parent div.
I can not touch so much of the web-page code so I'd need a solution requiring only modifications in the user-control's code behind.
So in the HTML "part" of the code of the web page I have this:
<div id="parentDIV" runat="server">
<uc:MyUserControl ID="myUserControlInstance" runat="server" />
</div>
I'd like to do in the code behind of the user-control something like this:
this.Container.Visible = false;
Note that I'm not asking if it is a good practise or not to do this.
EDIT:
The user-control code behind does not "know" about the ID of the parent DIV.
I would hide it on the client. Decorate your user control container (div?) with a class like "awesomeUserControl". Then emit some javascript using the ScriptManager object to hide the parent like this:
ScriptManager.RegisterStartupScript(this, this.GetType(), "HideMyAwesomeUserControl", "$('.awesomeUserControl').parent().hide();", true);
The better way...
What you should do is to create a custom event in your user control, to which your container will subscribe - very much like subscribing to a button event, only this is your custom control. This event passes information to your container which can then discern from it what it needs, such as whether or not the div should/not be visible.
It might look something like:
protected void Page_Load(object sender, EventArgs e)
{
this.myuserControl.Update += new MyUserControlUpdateEventHandler(myuserControl_Update);
}
void myuserControl_Update(object sender, MyuserControlEventArgs e)
{
this.parentDiv.visible = !e.ShouldHideUI;
}
This method will decouple your parent with the user control, i.e. your user control doesn't have to have any knowledge at all of the parent's controls, nor should it.
If you are curious, here is a rough example of how your user control will define such an event:
public class MyuserControlEventArgs : EventArgs
{
public bool ShouldHideUI { get;set;}
public MyuserControlEventArgs (bool shouldHideUI)
{
this.ShouldHideUI = shouldHideUI;
}
}
public delegate void MyUserControlUpdateEventHandler(object sender, MyuserControlEventArgs e);
public event MyUserControlUpdateEventHandler Update;
protected void OnUpdate(MyuserControlEventArgs e)
{
if (Update!= null)
Update(this, e);
}
Your user control will simply need to call OnUpdate whenever it feels its subscribers need to know about it.
The Quick and Dirty way...
If you need quick and dirty, then try this (inside your user control):
TheParentControl parentControl = (TheParentControl)this.Parent;
parentControl.ParentDiv.Visible = true;
The key is to cast to the appropriate type (apparently your user control would know what type of parent it has), then set the parent's property. You might expose your div as a property in the parent control. Note, that parent could be ANY control (page, FooControl, BarControl, whatever) whose control collection your user control resides. Once you get a handle to the parent, you can even FindControl() to find a control by name.
You're almost there....
this.Parent.Visible = false;
When all controls get rendered, the HTML Parent child controls can be determined like below.
I am using while loop, so in case you add some other intermediate control, it may not give crash or unexpected results.
public Control ParentControl
{
get
{
Control ctl = this.Parent;
while (true)
{
if (ctl == null) break;
if (ctl.ID.Equals("parentDIV"))
{
break;
}
ctl = ctl.Parent;
}
return ctl;
}
}
if(ParentControl != null)
ParentControl.Visible = true|false;
Am I missing something, it sounds like you have a usercontrol and an aspx page (both have code behind's).
The user control appears to have been added to the aspx page, wrapped in a div. YOu've made the div control runat server (though you can still do this via htmlcontrol).
All you ned to do to manage the div is:
parentDIV.visible = false;
or whatever you need to do with the div.
Why does the UC code behind need to know about the APSX pages DIV, it doesn't.

Pass values from page to user control

I am storing name and last name in two labels in main page. I also have those values in a class (class doesnt do much but i am using them for future expansion). I have a user control that will send an email with name and last name as body.
My question is that how can I transfer label or class variable values into user control's body variable?
Create a property on your user control with the datatype of the data you want to pass to it, and populate it in your page on creation of the control.
public class myUserControl : Control
{
...
public int myIntProperty {get; set;}
...
}
Later this in the code behind you can assign the value like
myUserControl cntrl = new myUserControl();
cntrl.myIntProperty = 5;
Instead of this you can pass the value through Markup also like
<uc1:myUserControl ID="uc1" runat="server" myIntProperty="5" />
You need to create properties on your control to hold these values; then from the page code, simply assign the values to the properties in the control.
On your control, you can have something like
public string FirstName
{
get {
if (ViewState["FirstName"] == null)
return string.Empty;
return ViewState["FirstName"].ToString();
}
set {
ViewState["FirstName"] = value;
}
}
You need to define public properties on the control and then when you use control on the page you can pass values to those parameters.
Something like:
<cc:mycustomControl runat="server"
MyProperty1=<%# label1 %>
MyProperty2=<%# label2 %>
/>
Step 1:
You can expost the values as property and than you can make use of that easily.
Step 2: To access your page from the user control you can make use of Parent property or may be some custome login to access the parent page and than write code to consume the property value.
you can do something like this in your user control
string x=((yourparentcontrol)this.parent).label1.text;
and use the string x.

How can i access a server side control from asp.net code behind file using reflection?

For example, if i have on the aspx page:
<asp:PlaceHolder ID="tab_0" runat="server" Visible="false"></asp:PlaceHolder>
<asp:PlaceHolder ID="tab_1" runat="server" Visible="false"></asp:PlaceHolder>
and i want to access these properties in the code behind page using values from a configuration file for example
string enabledTabs = "0,1,2,3";
if there a way i can use reflection to set them to enabled or disabled e.g.
foreach(var id in enabledTabs.Split(','))
{
// <use reflection to get the correct tab control>
// Set property of the tab
tab.Visible = true;
}
I could acheive the result i want by using a switch statement and setting the particular control property, but i'd like to use reflection to get the tab to make it cleaner.
Could anyone help?
Thanks!
You don't need reflection. Use Page.FindControl:
foreach(var id in enabledTabs.Split(','))
{
PlaceHolder control = (PlaceHolder)this.FindControl("tab_"+id));
control.Visible = true;
}
foreach(var id in enabledTabs.Split(','))
{
// Set property of the tab
Page.FindControl("tab_" + id.ToString()).Visible = true;
}
Try the following:
Control tab = Control.FindControl("tab_"+id);

C# custom control to get internal text as string

ok, I'm working on a custom control that can contain some javascript, and read this out of the page into a string field.
This is a workaround for dynamic javascript inside an updatepanel.
At the moment, I've got it working, but if I try to put a server tag inside the block:
<custom:control ID="Custom" runat="server">
<%= ControlName.ClientID %>
</custom:control>
The compiler does not like it. I know these are generated at runtime, and so might not be compatible with what I'm doing, but does anyone have any idea how I can get that working?
EDIT
Error message is: Code blocks are not supported in this context
EDIT 2
The control:
[DataBindingHandler("System.Web.UI.Design.TextDataBindingHandler, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ControlValueProperty("Text"), DefaultProperty("Text"), ParseChildren(true, "Text"), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class CustomControl : Control, ITextControl
{
[DefaultValue(""), Bindable(true), Localizable(true)]
public string Text
{
get
{
return (string)(ViewState["Text"] ?? string.Empty);
}
set
{
ViewState["Text"] = value;
}
}
}
The compiler is write, server side code blocks are only supported within the context of an ITemplate.
The "Text" property should be set like this ...
<custom:control ID="Custom" runat="server" Text="YourText">
Using ITemplate you can declare it in the codebehind as ...
public ITemplate Text
{
get;
set;
}
But then you would need to do this ...
<custom:control ID="Custom" runat="server">
<Text><%= ControlName.ClientID %></Text>
</custom:control>
Having said that, if you have a custom control why not just do this in the code behind ...
this.text = ((ITextControl)Page.FindControl(controlName)).Text;
Trouble is, it's not very dynamic.
I would favour the templated option.
Harder to implement though.

Instantiate User Control with Custom Attributes

My User Control has the following properties:
private String _requestIP;
public String RequestIP
{
get { return _requestIP; }
set { _requestIP = value; }
}
When adding a instance of the Control to an aspx page at design time it's easy to assign the attributes which can be utilized in the codebehind file...
<uc:Item ID="Testing" runat="server" RequestIP="127.0.0.1" />
However, if I try to create the control at runtime in the aspx.cs file, how am I able to assign values to these attributes?
Control ItemX = (Control)Page.LoadControl("/controls/item.ascx");
There is no ItemX.Attributes.Add() method which I would expect to be there, and no ItemX.RequestIP property to set.
Is there a way to set this dynamically in the aspx page using <%= Users_IP_Address %> tags or some other method?
Well, you just need to cast it to the appropriate type (whatever the class name of your user control is).

Categories

Resources