我有一个带有标签的父用户控件。在父的OnInit上,我动态加载子控件。从子控件,我需要将父标签设置为某个东西。
使用Parent属性返回直接父级,在我的情况下实际上是PlaceHolder。从理论上讲,我可以递归循环来获取对父用户控件的引用。我在这里朝着正确的方向前进吗?有这么简单的方法吗?
我有一个带有标签的父用户控件。在父的OnInit上,我动态加载子控件。从子控件,我需要将父标签设置为某个东西。
使用Parent属性返回直接父级,在我的情况下实际上是PlaceHolder。从理论上讲,我可以递归循环来获取对父用户控件的引用。我在这里朝着正确的方向前进吗?有这么简单的方法吗?
试着抓住孩子的 NamingContainer。
试着抓住孩子的 NamingContainer。
或者您可以遍历父项,直到找到所需的控件,例如使用扩展方法。
public static Control GetParentOfType(this Control childControl,
Type parentType)
{
Control parent = childControl.Parent;
while(parent.GetType() != parentType)
{
parent = parent.Parent;
}
if(parent.GetType() == parentType)
return parent;
throw new Exception("No control of expected type was found");
}
有关此方法的更多详细信息: http://www.teebot.be/2009/08/extension-method-to-get-controls-parent.html
对我来说,正确的方法是在控件中公开一个add方法。 现在,如果您需要更新其外部的标签,请公开一个事件,例如OnCollectionChanged(...),并从需要显示该集合信息的控件中获取。
这样每个控件都可以完成它的所有部分 固体
@Rex M为此提供了一个简单易用的解决方案,只是为了扩展它以显示用法:
从子用户控件中使用此代码段来访问父用户控件属性:
((MyParentUserControlTypeName)NamingContainer).Property1 = "Hello";
有一个FindControl方法,但如果我没记错的话它不是递归的。 另外,您并不保证page_init上存在所有控件层次结构,在访问控件之前等待直到page_load。 Init用于创建它们。
您可以将父项的引用传递给子项,并在父项上公开一个方法来设置标签,尽管这会非常紧密地耦合对象。否则,您可以在子项上公开一个属性,然后父项可以检查并设置它自己的标签。
你可以采用几种不同的方式...一种方法是将一个Parent属性添加到你的Child类......然后执行:
// in the context of parent's loading of child:
child.ParentObject = self;
我相信有人会回来说这违反了一些最佳做法或其他......但是 耸。如果你想保持一些分离,你也可以使用事件。
如果您通过代码创建UserControl,为什么不将强类型父项传递给构造函数。
public class MyUserControl1 : UserControl
{
public void Init(...)
{
var uc2 = new MyUserControl2(this);
}
}
public class MyUserControl2 : UserControl
{
private MyUserControl1 parentUserControl;
public MyUserControl2(MyUserControl1 parent)
{
this.parentUserControl = parent;
}
}
现在这是紧密耦合的,可能会在以后引发问题,但对于这种情况,它可以工作。
你最好的办法是等到page_load完成然后递归搜索Page.Controls。
以下是一些扩展方法,可以帮助您实现:
var control = Page.GetControl(MyControlID);
public static class ControlExtensions
{
public static IEnumerable<Control> Flatten(this ControlCollection controls)
{
List<Control> list = new List<Control>();
controls.Traverse(c => list.Add(c));
return list;
}
public static IEnumerable<Control> Flatten(this ControlCollection controls, Func<Control, bool> predicate)
{
List<Control> list = new List<Control>();
controls.Traverse(c => { if (predicate(c)) list.Add(c); });
return list;
}
public static void Traverse(this ControlCollection controls, Action<Control> action)
{
foreach (Control control in controls)
{
action(control);
if (control.HasControls())
{
control.Controls.Traverse(action);
}
}
}
public static Control GetControl(this Control control, string id)
{
return control.Controls.Flatten(c => c.ID == id).SingleOrDefault();
}
public static IEnumerable<Control> GetControls(this Control control)
{
return control.Controls.Flatten();
}
public static IEnumerable<Control> GetControls(this Control control, Func<Control, bool> predicate)
{
return control.Controls.Flatten(predicate);
}
}