ASP.NET:公开Web用户控件的控件

时间:2022-08-12 21:12:32

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.

我已经创建了一些Web用户控件(.ascx文件)并将它们放入Pages中。用户控件中有一些TextBox,我希望Page能够直接访问。

What's the easiest (read: least time) way to expose these TextBoxes in the user controls to the Pages containing the user controls?

将用户控件中的这些TextBox暴露给包含用户控件的Pages的最简单(读取:最少时间)方法是什么?

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.

我知道的两个选项是从Pages调用myUserControl.FindControl(id)(这甚至可以从Page?),并在用户控件中编写属性来公开TextBox值。

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.

似乎都不理想。 FindControl()要求Page知道用户控件中TextBox的ID,从而破坏封装并添加硬编码字符串,并且在用户控件中编写一堆属性将非常耗时,因为这些用户中的TextBox数量很多控制。

There's no way to declare these TextBoxes in my user controls be public instead of protected?

没有办法在我的用户控件中声明这些TextBox是公共的而不是受保护的?

5 个解决方案

#1


(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.

如果您使用的是Web应用程序类型项目,则每个UserControl都应该有一个designer.cs文件。它包含每个子控件的声明,因此您可以将访问修饰符更改为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.

如果您使用的是网站类型项目,则应该转换为Web应用程序。根据Microsoft(以及经验支持),当您计划编写跨越单个代码隐藏的大量代码时,不应使用Web站点类型。

#2


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.

如果我必须这样做,我会写一个暴露控件的公共属性。但是,通常有一种方法可以重写信息,这样您就不需要公开内部控件。如果您需要的只是值,请创建一个返回值的属性。如果您需要客户端ID,则创建公开值或事件的客户端对象可能会解决问题。请记住,一旦你公开,你就会暴露合同,改变合同几乎总是很痛苦。

#3


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):

您可以将其作为属性从后面的代码中公开。你真的只能从代码中访问它的属性,而不是从ASP.Net设计者那里访问它的属性。这是vb中的一个示例,它在用户控件上公开DropDownList(并且,它可能不是最佳实践,但它肯定胜过编写代码以公开子控件上的每个属性):

''' <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

#4


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?

为什么不让用户控制TextBoxes的集合,将集合公开为属性,在Init()方法中,只需将所有文本框添加到集合中?

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.

这样,你有一个集合,你可以根据需要搜索ID,而不依赖于任何页面逻辑,你只需要暴露一个属性。如果您为它创建自己的集合类,您甚至可以使用几种方便的方法来编写以您需要的方式访问文本框的方法。

#5


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.

从公共基类派生所有Web用户控件,并将此功能公开为公共方法(或方法)。您的基类可以从UserControl派生(通常是.ascx的方式),而您的控件又从它派生。

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:

因此,如果您只需要从父级获取id的文本框值,则可以向基类添加以下内容:

    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.

我会说这条路线与先前建议将TextBox公开的原因是因为你真的只想从父级读取文本值而不是将整个对象公开为读/写。

#1


(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.

如果您使用的是Web应用程序类型项目,则每个UserControl都应该有一个designer.cs文件。它包含每个子控件的声明,因此您可以将访问修饰符更改为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.

如果您使用的是网站类型项目,则应该转换为Web应用程序。根据Microsoft(以及经验支持),当您计划编写跨越单个代码隐藏的大量代码时,不应使用Web站点类型。

#2


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.

如果我必须这样做,我会写一个暴露控件的公共属性。但是,通常有一种方法可以重写信息,这样您就不需要公开内部控件。如果您需要的只是值,请创建一个返回值的属性。如果您需要客户端ID,则创建公开值或事件的客户端对象可能会解决问题。请记住,一旦你公开,你就会暴露合同,改变合同几乎总是很痛苦。

#3


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):

您可以将其作为属性从后面的代码中公开。你真的只能从代码中访问它的属性,而不是从ASP.Net设计者那里访问它的属性。这是vb中的一个示例,它在用户控件上公开DropDownList(并且,它可能不是最佳实践,但它肯定胜过编写代码以公开子控件上的每个属性):

''' <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

#4


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?

为什么不让用户控制TextBoxes的集合,将集合公开为属性,在Init()方法中,只需将所有文本框添加到集合中?

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.

这样,你有一个集合,你可以根据需要搜索ID,而不依赖于任何页面逻辑,你只需要暴露一个属性。如果您为它创建自己的集合类,您甚至可以使用几种方便的方法来编写以您需要的方式访问文本框的方法。

#5


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.

从公共基类派生所有Web用户控件,并将此功能公开为公共方法(或方法)。您的基类可以从UserControl派生(通常是.ascx的方式),而您的控件又从它派生。

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:

因此,如果您只需要从父级获取id的文本框值,则可以向基类添加以下内容:

    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.

我会说这条路线与先前建议将TextBox公开的原因是因为你真的只想从父级读取文本值而不是将整个对象公开为读/写。