How dan I dynamically create some public properties on a custom webcontrol.
For example, web control has 5 TextBox controls. I need a public property for each TextBox control to be able to set a specific property of the TextBox control.
I want to be able to loop the controls in the webcontrol and create a public property for each TextBox control.
any ideas?
Edited:
If the child-controls are present at Design-Time then you need to explain why you want to dynamically add properties to access the control members--unless there is a good reason it just sounds like a poor design.
Here's my suggestion:
Leave your controls as Friend or Private -- don't expose them directly (it leads to tight-coupling and gets nasty over time).
Expose a new public property that gets/sets the corresponding property on 1x of your controls; so if you want to set .Text on 5x TextBoxes you'll have 5x properties.
Be done with it.
If you're trying to be clever by dynamically adding them, then it's a good intention that will lead to poor results. Just remember: KISS (Keep it simple, stupid!).
You could create a property like this
private TextBox[] textBoxes; //declared as a class member variable
public TextBox[] TextBoxes
{
get
{
if (textBoxes == null)
{
textBoxes =(from ctrl in this.Controls.OfType<Control>()
where ctrl is TextBox
select (TextBox)ctrl).ToArray();
}
return textBoxes;
}
}
Exposing the controls contained in a WebContol (or any class for that matter) is not a good design as it makes your code brittle and hard to maintain. You should put code that directly manipulates the TextBoxes inside the WebControl.
Related
My page contains several web user controls. Those controls contains other child controls, and those contains more child controls and so on. From my page, I want to be able to access those controls, like I do with other public classes: uc1.uc1_child1.uc1_child1_child1.Update();
(I do know about the FindControl method, and thats what Im currently using. It's however not type safe, and I need to lookup the names of the controls all the time to be on safe side. Much more time consuming than intellisense)
If you create a public property on your usercontrol for each of the usercontrols it contains, that should work.
eg
public SpecificUserControlType ContainedUserControl
{
get
{
return this.uc1_child;
}
}
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.
I have a UserControl that provides some functionality (loads and displays a client's information) and I want to extend that UserControl. Some forms require the plain old UserControl while other forms will require some additional fields. How can I inherit from the existing UserControl, maintain the existing fields but add new fields on as well?
I like the way MasterPages work, where you define place holders, and then the content pages just fill those places holders with extra content. Is this possible with UserControls? Thanks!
Perhaps you could define a few ASP:PlaceHolders (think of it as "zones") within your UserControl and make them available via public (or protected if you only want the inherited class to be able to change them) properties. That way you can add subcontrols to them whenever you need to.
protected PlaceHolder TopZone {
get { return plhTop; }
}
protected PlaceHolder BottomZone {
get { return plhBottom; }
}
From one of the inherited UserControls:
Label lblTest = new Label { Text = "Hello World!" };
TopZone.Controls.Add(lblTest);
It's a verrry basic example, I hope it is of use to you.
I ended using nested MasterPages as my UserControls (as they inherit from UserControl anyway). Then I just call this.LoadControl("~/mp.master") and voila, I have nested UserControls with full design-time support. :)
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.
Does anyone know of a good tutorial that demonstrates using an existing AJAX control extender in a Custom ASP.NET Server Control?
I do not want to build a "Custom AJAX Server Control". I want to build a Custom Server Control that uses an existing AJAX control extender.
I would like to combine an asp:TextBox, asp:ImageButton, asp:CustomValidator (with client side javascript from an embedded resource), and an ajax:CalendarExtender into one custom server control. Or has this already been created?
Any help would be greatly appreciated. Thanks.
UPDATE: Basically, I would like to create a CompositeControl that has an ajax:CalendarExtender as a child control.
Sounds like what you're after is a composite control. They are pretty much exactly like a user control only instead of using the ascx file to create the controls you create them all programmatically. The big advantage of doing this over using a user control is you end up with something you can put in an assembly and use in different projects.
A composite control can inherit from either Control or WebControl. I personally usually find Control more useful to inherit from because I usually don't need a lot of the extra stuff you get from WebControl such as the styling properties since I usually just style through a single CssClass property.
You'll also need to make sure your class implements the INamingContainer interface. This will make sure that each child control will automatically get a unique name if the control is used multiple times in the same parent container.
The most important thing to do when creating a composite control is to override Control's CreateChildControls method. All the logic for actually creating the controls should go in here. The framework will automatically make sure that this gets called at the right time in the page lifecycle.
Here's a little example:
public class MyCompositeControl : Control, INamingContainer
{
protected override void CreateChildControls()
{
Controls.Clear();
var textbox = new TextBox();
textbox.ID = "TextBox1";
Controls.Add(textbox);
if (!Page.IsPostBack || !IsTrackingViewState)
{
// make sure you set the properties after
// you add it to the parent or the viewstate
// won't save properly
textbox.MaxLength = 30;
}
var button = new Button();
button.ID = "Button1";
Controls.Add(button);
if (!Page.IsPostBack || !IsTrackingViewState)
{
button.Text = "Save";
}
}
}
I don't think ASP.NET AJAX should complicate this much. The only thing I can think of ist you'll need to make sure that you create a ScriptManager on whatever page the composite control will be added to.
There's a full example of this on the MSDN site. There's another nice example on this blog.
What you want is to build a user control and not a custom control most probably. A user control is a composite control whereas a custom control is a control built either from the ground up either derived from a basic control.
I would suggest you search on MSDN. I have seen several good articles about that topic in their magazines over the last year or two, that have been fairly thorough. But I don't have links to them and I'm too lazy to Google for you. :\