我有一个ChildUserControl,它被加载在ParentUserControl中。主机页面加载ParentUserControl。
我需要从ChildUserControl访问ParentUserControl的属性。
感谢您的时间。
我有一个ChildUserControl,它被加载在ParentUserControl中。主机页面加载ParentUserControl。
我需要从ChildUserControl访问ParentUserControl的属性。
感谢您的时间。
由于平台/语言等不明确,因此这个答案必然是含糊的... 但是通常情况下,子控件不能直接访问父控件的属性,因为多种不同类型的父控件都可以托管子控件。子控件不应该被硬编码到单一的父控件中,否则它可能就像是父控件的一部分。
通常,您可能想尝试简单地删除这个要求 - 这听起来像是一种奇怪的设计。但是,一些框架支持类似于此的功能-例如WPF中的依赖属性。
基于接口的设计(对于父对象)是一种方法,但这并不太干净。对于.NET,事件等是子元素与父元素通信的另一种常见方式-子元素公开事件,不同的父元素可以以不同的方式使用这些事件。
除此之外,您将涉及测试/强制转换父对象(针对类或接口),以从父对象中访问详细信息-例如:
ParentControlType parent = this.Parent as ParentControlType;
if(parent != null) {
// access properties etc of "parent"
}
(这里也可以使用接口; 无论哪种方式都有点笨拙...)
个人而言,与其从子类中使用这种类型的强制转换,我更喜欢父类掌控;父类在子类上设置属性并侦听事件,而不是子类将属性设置回父类:
// in the parent
child.SomeProperty = 132;
child.SomePropertyChangd += delegate {
// do something at the parent
};
这样,子组件不知道也不关心它的父组件是谁。它只知道自己有属性等,并且可以通知其他人发生了有趣的变化。
通过 ((ParentType)Me.Parent) 可以从子控件访问父级。但这不被推荐。无法知道该控件是否会在另一个页面/控件中使用。编译器不会捕获这一点,该强制转换会在运行时引发异常。
最好的处理方式是,父控件提供子控件需要的任何信息(在控件上创建公共属性或方法)。甚至可以意味着父控件为子控件提供其自身的强类型引用(可能通过接口)。这样,编译器就能确保您不会遇到子控件假定错误类型的父控件的情况。
UC1.ascx
|— UC2.ascx
在UC1.ascx中,您定义一个公共函数或属性来执行所需操作:
fnUC1(param)
在UC2.ascx中,您可以通过以下代码访问此函数:
CType(Parent.Parent,UC1).fnUC1(param)
CType(Parent.Parent.Parent,UC1).fnUC1(param)
我承认这不是“艺术的状态”...但它适用于始终一起工作的嵌套控件,例如父(UC1)/子(UC2)数据显示。
希望这会有所帮助。
Pierre。
很抱歉没有表达清楚。平台是.NET,语言是C#。
我有一个单一的父控件,它托管多个子控件。这是在C#中实现可视化继承的一种方式,因为有许多UI控件是在子控件之间共享的。
通过接口设计,您是否建议父控件和子控件都实现一个公共接口?
感谢回复。
我会考虑使用反射。不过,我听说它有性能瓶颈。
Jim - 你说:
~~
最好的处理方法是让父控件提供子控件需要的任何信息(在控件上创建公共属性或方法)。这甚至可能意味着父控件向子控件提供其自身的强类型引用(可能通过接口)。这样编译器就可以确保您不会出现子控件假设了错误类型的父控件的情况。~~
在我的情况下,父类和子类都实现了相同的接口。这是不好的设计吗?如果我在接口中添加一个父类引用的属性,考虑到父类也实现了相同的接口,这会起作用吗?public static T GetData<T>(this Control c, string propertyName, T defaultValue){
Type t = obj.GetType();
var prop = t.GetProperties().FirstOrDefault(p => p.Name == propertyName);
if(prop == null) return defaultValue;
else {
object val = prop.GetValue(obj, null);
if(val == null) return defaultValue;
else return (T)val;
}
}
这个简单的扩展方法扩展了“Control”,但你可以轻松地将其放在任何东西上(当我传递匿名类时,我曾经在object
上使用它,这本身就是一个坏主意!)
然后使用方法如下:
string someData = this.Parent.GetData("someProperty", string.Empty);