Design time validation of custom ASP.NET server controls - asp.net

I am creating a custom control which has some properties on it. The problem is that the control isn't valid without those properties being set and there aren't suitable default values for them.
How can I make sure that they are being set in the ASP.NET markup when being included on the page? Is there some kind of validation event that can be hooked into?
For example, the following control:
public class TestControl: Control
{
public string Source { get; set; }
}
At design/compile time there should be an error if the control is used without setting the Source property:
<Prototype:TestControl runat="server"></Prototype:JavaScriptInclude>
I know I could check this at runtime, but it would be nice to have some early checking going on as it could be overlooked if the validation is deferred until runtime.

Short answer: you cannot.
Controls should have default behavior if properties aren't set. Only way to facilitate this is by bypassing the adding of the control in the aspx page, and do all this in your codebehind where you'll have the default language constructs like constructors. But I assume you know that path :-)

Related

ASP.NET 4.0: Is it possible to make some user control's child controls public without using FindControl or public properties?

I have a custom user control that contains text boxes, dropdowns, etc. I need these controls to be public so that I can go like ucEmployeeAddress.txtAddr1.Text from outside the control.
I know that I can use public properties in the control that return an instance of the control inside or use FindControl to locate my control from outside the user control, but I don't want to do that due to excess code.
If there is no way to do what I want then I will just go the public property route.
Edit: Would the person who thumbed my question down be so kind as to explain how my question shows lack of research effort, is unclear, or not useful?
You just need to expose a property in the user control:
public string Address
{
get
{
return txtAddr1.Text;
}
set
{
txtAddr1.Text = value;
}
}
Do you really need to expose the entire control ?
If its just the text property you could just expose that.
public string TitleText
{
get { return this.txtTitle.Text;}
}
If you really need the control i would suggest exposing it via a property, consumers may not even know the existance or name of the control, and nor should they care about your internal workings - using FindControl is a poor solution from outside of the control.
public TextBox TitleTextBox
{
get { return this.txtTitle;}
}
As an alternative you may be able to modify the visual studio templates to expose all your controls as public, however im not sure if this is such a great idea or how you would do it..
Well, about three hours later, I finally came upon a solution. I don't know if this is new in VS2010, but you can actually edit the user control's designer and turn all members from Protected to Public. I swear I've tried this with earlier versions of VS in the past without success, but it's apparently working for me now.
What's interesting is that the IDE has a keen sense of what parts of the designer it should and should not regenerate. For example, if you comment out the entire contents of the designer class, it will not regenerate the commented-out members. To get it to regenerate them, you have to completely delete the members that you want regenerated. What's also cool is that you can comment out the entire designer class's contents, switch back to the markup and add a server control like a textbox, and flip back to the designer to discover that it generated the member definition for only that control while the rest of the member references remain commented-out. Edit: And if you delete a control from the markup whose designer member you had modified from protected to public, it will still delete the reference from the designer.
I will note that I am also using VB.NET. I would have to assume this works with C#, as well, but cannot say for sure.
The proper way to do this is through event bubbling. This way you can keep the implementation of your controls hidden while being able to modify the properties that you chose.
This link does a good job explaining how to accomplish this.
As a side note, you should be more concerned with the elegance of your code than the amount of it.
If you take the time to implement event bubbling, for example, as opposed to exposing the control's children as public, any manipulation of the control's children is handled by that control. This makes it easy to maintain if ever the logic of manipulation were to change, and easy to implement across your entire application.
However, if you expose your control's children as public instead, you must repeat that manipulation everywhere it is used.
Therefore, the "excess code" will both improve the quality of your code and actually decrease this "excess code" you are concerned about.

Add 'Current' property to ASP.NET control

I have some control. I add one instance of this control to every Page in OnInit event and I want to access this control in other places in this way: Sample.Current
public class Sample : Control
{
public static Sample Current
{
get
{
// ???
}
}
}
Can you tell me what is the best way to do this property implementation?
It would be good to have a bit more detail - what is this class' purpose? But I'll attempt to help anyway:
You'll be able to access that control from within code on the page , if it's referenced in the code and not added dynamically somehow at runtime. ie if it's a variable of the page declared like:
Sample ctrl = new Sample();
Then later you can reference it using ctrl.Current in your code.
FYI - if you want a place to reference classes and variables for a page's lifecycle, you may want to check out HttpContext.Current.Items http://www.mikeduncan.com/3-hot-uses-for-httpcontextcurrentitems-they-wont-tell-you-about/ It's like a session bag that only exists for a single page request - for example if you have a class that holds information about a user that you need to access many times from many different controls on the page, you could just stick that class into the Items collection and then reference it from any code that runs on your page.
HTH,
Lance

Is it possible for a custom asp.net control to load types at design time from the assembly hosting the control?

I have a custom server control for asp.net. One of the properties available to it is a generic object. That generic object has custom attributes that are read and used to customize the rendering of the control.
At run time, this is no problem, since all I need to do is find all the attributes on the instance that gets passed into the control.
However, just as the "DataSource" member of controls can call up a list of object types at design time, I would like to be able to bring up a list of types in the host assembly. There is no need for actual instances, since I'm rendering based on attributes.
This is an example property from the host control:
[Browsable(true)]
[TypeConverter(typeof(TheObjectConverter))]
public object TheObject
{
get { return _theObject; }
set { SetTheObject(value); }
}
What I want to have happen is to have TheObjectConverter be able to load the assembly of the host page for the control.
None of the following seem to work
.GetReferencedAssemblies();
.GetExecutingAssembly();
.GetCallingAssembly();
.GetEntryAssembly();
.GetAssembly();
I even a full recursion against .GetReferencedAssemblies(), with no luck. It seems I am unable to load the assembly of the control's host at design time. Is that correct, or is there a way to do this?

Validate - Web User Control

I do not like to use the calendar from .NET, so I would like to have one Web User Control with 3 drop down boxes, day, month, year. [CODE DONE].
I want to be able to call this Control and initialize it with start year and end year, and with or without selected date.[CODE DONE].
This control will see if there is one valid date selected and return bool [CODE DONE].
Then in my web page I would like to able to see if that web user control is valid, in a way that I can use with the normal .NET validation (associate one required field), the problem is that I don't know where to put this code and retrieve it to the validation control on the web page. [CODE NOT DONE].
How can I do this?
There are two steps to integrating your custom server controls with the validation framework.
(1) Server side: you'll need to add a ValidationPropertyAttribute to your class, so the validation framwework knows what to look at when validating:
[ValidationProperty("SelectedDate")]
public class MyDateControl : WebControl
{
public DateTime? SelectedDate { get { ... } set { ... } }
}
(2) To hook up with client side validation, you have to make sure there's an input tag associated with your control. One way of doing that is rendering an <input type="hidden"> as the first child tag of your web control's HTML. The validation framework will pick up on that. The remaining thing to do here, is to set this hidden field through JavaScript each time your one drop downs changes.
This way, you can tie in with the existing validation controls. If you want different way to validate, you should look at a CustomValidator.
You want to use the CustomValidator control for this. See this tutorial that explains how to implement it with both a client-side and server-side version of the validation.

ASP.NET: Exposing a Web User Control's controls

I've created some Web User Controls (.ascx files) and dropped them into Pages. The user controls have some TextBoxes in them that I'd like the Page to be able to access directly.
What's the easiest (read: least time) way to expose these TextBoxes in the user controls to the Pages containing the user controls?
The two options I know are calling myUserControl.FindControl(id) from the Pages (does this even work from the Page?), and writing properties in the user controls to expose the TextBox values.
Neither seem ideal. FindControl() requires the Page know the IDs of the TextBoxes in the user controls, thereby breaking encapsulation and adding hard-coded strings, and writing a bunch of properties in the user controls will be very time consuming given the number of TextBoxes in these user controls.
There's no way to declare these TextBoxes in my user controls be public instead of protected?
(Setting aside the obvious comments about the fact that what you're describing is essentially the opposite of best practice...)
If you are using a Web Application type project, you should have a designer.cs file for each UserControl. That contains the declaration of each child control, so you can change the access modifier to public.
If you are using a Web Site type project, you should probably convert to Web Application. According to Microsoft (and backed up by experience), the Web Site type is not intended for use when you plan to write extensive code which spans beyond a single code-behind.
If I have to do this I will write a public property that exposes the controls. However there is usually a way to rewrite the information such that you don't need to expose the internal controls. If all you need is the value, create a property that returns the value. If you need client ids, perhaps creating a client object that exposes values or events will solve the issue. Remember, once you make it public, you are exposes a contract and changing that contract will almost always be painful.
You can expose it as a property from the code behind. You'll really only be able to access it's properties from code, not from the ASP.Net designer though. This is an example in vb that exposes a DropDownList on a user control (and, it may not be a best practice but it certainly beats writing code to expose every property on the child controls):
''' <summary>
''' This is the exposed DropDownList for this control.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property DrowDownList() As DropDownList
Get
Return ddControlList
End Get
End Property
Why not give your user control a collection of TextBoxes, expose the collection as a property, and in your Init() method, just add all your textboxes to the collection?
That way, you have a collection that you can search by ID if you ever need to, without relying on any page logic, and you only have to expose one property. If you make your own collection class for it, you could even program in a couple of handy methods for accessing the textboxes the way you need to.
Derive all of your Web User Controls from a common base class and expose this functionality as a public method (or methods). Your base class can derive from UserControl (the way an .ascx normally would) and your controls in turn derive from it.
Then, even if using reflection seems like a bit of work, you're only doing it once. If the textboxes are dynamic and you want to avoid hardcoding things, this would be the way to go.
So, if you need to just get the value of the text box by id from a parent, you can add something like the following to your base class:
public string GetTextboxValue(string id)
{
string textValue = string.Empty;
Control ctl = FindControl(id);
if (ctl.GetType() == typeof(TextBox))
textValue = ((TextBox)ctl).Text;
return textValue;
}
I'd say to go this route vs. the previous suggestion of making the TextBox public since you really only want to read the text value from the parent and not expose the entire object as read/write.

Resources