简体   繁体   English

如何找到控件或嵌入控件的页面

[英]How to find a control or page a control is embedded In

I've written a web user control which I want to be able to drop into the markup for either aspx pages or other web user controls. 我已经编写了一个Web用户控件,希望它可以放入aspx页面或其他Web用户控件的标记中。

I need my user control to be able to easily and efficiently work out if its inside another user control or an aspx page. 我需要我的用户控件能够轻松高效地解决它是否在另一个用户控件或aspx页面中的问题。 My initial idea is to do it recursively with checks on the Parent property - continue looking up the nesting hierarchy until I find either a web form or a user control - but I'm not sure this the best way of going about this. 我最初的想法是通过对Parent属性的检查来递归地进行操作-继续查找嵌套层次结构,直到找到Web表单或用户控件为止-但我不确定这是实现此目的的最佳方法。

Can you suggest an easier way? 您能建议一种更简单的方法吗? Thanks. 谢谢。

Recursively check the type of your Parent until Parent.GetType() is either typeof(UserControl) or type(Page) 递归检查Parent的类型,直到Parent.GetType()typeof(UserControl)type(Page)

private bool IsAncestorTypeOf(Control c, params Type[] typesToCheck)
{
   var parent = c.Parent;

   if (parent == null) return false;    
   if (typesToCheck.Contains(parent.GetType())) return true;

   return IsAncestorTypeOf(parent, typesToCheck);
}

Or the same without recursion 还是一样没有递归

private bool IsAncestorTypeOf(Control c, params Type[] typesToCheck)
{
   var parent = c.Parent;

   while (true)
   {
       if (parent == null) return false;    
       if (typesToCheck.Contains(parent.GetType())) return true;

       parent = parent.Parent;
   }
}

Call it like 像这样称呼它

var isAncestorPageOrUserControl = IsAncestorTypeOf(this, typeof(Page), typeof(UserControl));

or 要么

var isAncestorPage = IsAncestorTypeOf(this, typeof(Page));
var isAncestorUserControl = IsAncestorTypeOf(this, typeof(UserControl));

Generally, components should be unaware of their arbitrary containers, although the containers must know their components (unless it's a strong dependency situation like list items are always in a list type and you can make a strong two way relationship). 通常,组件应该不知道其任意容器,尽管容器必须知道其组件(除非存在强烈的依赖关系,例如列表项始终处于列表类型,并且可以建立牢固的双向关系)。 However it sounds like you are reaching out into the general surroundings. 但是,听起来您正在接触周围的环境。 You might find many cases to code for doing this and accidentally miss others. 您可能会发现许多情况下要进行编码,而无意间错过了其他情况。


By making the user control aware of its surroundings and the larger world you may be introducing dependencies that make your control less reusable and harder to maintain. 通过使用户控件了解其周围环境和更广阔的世界,您可能会引入依赖关系 ,从而使控件的重用性和维护难度降低。

If something the control needs is outside of itself, you might move toward composition by forcing the developer to provide a reference to the needed thing on a property of your user control. 如果控件需要的东西不在其自身之外,则可以通过强制开发人员在用户控件的属性上提供对所需内容的引用来转向合成 This is the way, for example, that validation controls in ASP.NET do it, to reference an external control to validate by id. 例如,ASP.NET中的验证控件就是通过这种方式来引用外部控件以通过id进行验证的。

Of course what I specified is practical only some of the time. 当然,我指定的只是部分时间是实际的。 Is there a specific reason or edge case why you need to make your user control look around itself, or can you get away with providing instructions to the developer about where the control should be used? 是否有特定的原因或特殊情况导致您需要使用户控件环顾四周,还是可以避免向开发人员提供有关控件应在何处使用的说明?

This should work: 这应该工作:

C# C#

bool inPage = (this.NamingContainer == this.Page);

VB.NET VB.NET

Dim inPage as Boolean = Me.NamingContainer is Me.Page

Edit : it seems to be not as simple as i hoped. 编辑 :这似乎不像我希望的那么简单。 If the usercontrol resists in a control like a GridViewRow, the NamingControl of it would be the Row and not the Page. 如果usercontrol拒绝使用诸如GridViewRow之类的控件,则其NamingControl将是Row,而不是Page。

This takes it into account: 这考虑到了:

C# C#

public static bool isControlInPageOruserControl(Control uc)
{
 bool inPage = uc.NamingContainer is Page;
 if (inPage) {
  return true;
 } else if (uc.NamingContainer is UserControl) {
  return false;
 } else {
  return isControlInPageOruserControl(uc.NamingContainer);
 }
}

VB.NET: VB.NET:

Public Shared Function isControlInPageOruserControl(ByVal uc As Control) As Boolean
    Dim inPage As Boolean = TypeOf uc.NamingContainer Is Page
    If inPage Then
        Return True
    ElseIf TypeOf uc.NamingContainer Is UserControl Then
        Return False
    Else
        Return isControlInPageOruserControl(uc.NamingContainer)
    End If
End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM