如何从页面后台代码向ASP.NET用户控件传递函数
你遇到的这个错误很典型——ASP.NET的控件属性绑定系统只能处理字符串、数值这类简单类型,没法自动把你写的方法名字符串转换成System.Action委托对象,所以直接在ASCX标签里赋值肯定行不通。下面给你两种可行的解决方案,推荐用第一种,更贴合WebForms的设计模式:
方案一:使用标准事件(推荐)
这是ASP.NET控件交互的标准做法,把用户控件里的Action属性改成事件,和普通Button的OnClick事件逻辑一致。
第一步:修改用户控件代码
把原来的Action属性替换成EventHandler类型的事件,触发事件时要先检查有没有订阅者:
public partial class uc_SaveCriteriaControl : System.Web.UI.UserControl { // 定义事件,匹配EventHandler委托签名 public event EventHandler SelectedCriteriaChanged; public event EventHandler Reset; public event EventHandler Save; protected void SelectionUpdated(object sender, EventArgs e) { // 安全触发事件,避免空引用 SelectedCriteriaChanged?.Invoke(this, e); } protected void Reset(object sender, EventArgs e) { Reset?.Invoke(this, e); } protected void Save(object sender, EventArgs e) { Save?.Invoke(this, e); } protected void Page_Load(object sender, EventArgs e) { } }
第二步:在页面中绑定事件
现在可以像用普通ASP.NET控件一样,在ASCX标签里用On[事件名]的格式绑定页面已有的方法:
<uc3:CriteriaControl runat="server" OnSave="imgbtnSaveParam1_Click" OnReset="imgbtnResetParams_Click" OnSelectedCriteriaChanged="MyParams_SelectedIndexChanged" />
你的页面里原来的imgbtnSaveParam1_Click这些方法签名本来就是protected void 方法名(object sender, EventArgs e),刚好和EventHandler的要求匹配,完全不需要修改页面的方法代码,直接复用就行。
方案二:手动在后台赋值委托
如果你坚持想用Action属性的方式,那不能在ASCX标签里赋值,得在页面的后台代码里手动把方法绑定到用户控件的委托上:
第一步:保留用户控件的原有代码
你的用户控件代码不用改,还是原来的Action属性那一套。
第二步:在页面后台绑定委托
在页面的Page_Load或者Page_Init事件里,手动把页面的方法赋值给用户控件的属性:
protected void Page_Load(object sender, EventArgs e) { // 给用户控件的委托属性赋值,直接引用页面方法 CriteriaControl1.SaveFunction = imgbtnSaveParam1_Click; CriteriaControl1.ResetFunction = imgbtnResetParams_Click; CriteriaControl1.SelectedCriteriaChanged = MyParams_SelectedIndexChanged; }
注意要给用户控件加上ID属性,这样后台才能引用到:
<uc3:CriteriaControl runat="server" ID="CriteriaControl1" />
另外要确保页面里的这些方法是protected或者public修饰的,不然用户控件访问不到。
总结
优先选方案一,事件是WebForms的标准组件通信机制,代码更符合框架规范,后续维护和扩展也更方便。方案二虽然能实现,但属于偏门用法,容易让其他开发者困惑。
内容的提问来源于stack exchange,提问作者Chris

