C# WebForms:如何在类级别一次性初始化FormView中的控件?
解决C# WebForms中重复初始化FormView控件的问题
你遇到的CS0236错误,本质是两个原因:
- WebForms页面生命周期中,类字段初始化的时机早于FormView等控件的初始化,此时
FormView1还未被实例化,调用FindControl必然失败; - C#语法规则不允许在实例字段的初始化器中引用另一个非静态实例成员(
FormView1是页面类的实例成员)。
以下是两种可行的解决方案,能一次性初始化控件、避免重复调用FindControl:
方案一:在页面Init/Load事件中统一初始化控件
利用WebForms的页面生命周期,在Page_Init或Page_Load事件中完成所有控件的初始化——这两个阶段中FormView的控件树已经构建完成,能安全调用FindControl。
代码示例:
public partial class WebForm1 : System.Web.UI.Page { // 声明类级别的控件变量(仅声明,不初始化) private CheckBox _mortgage; private Literal _grossProfitPcm; private TextBox _rentalPcm; private TextBox _reversionaryRateAbr; private TextBox _capitalAmount; private DropDownList _ddlPropertyID; protected void Page_Init(object sender, EventArgs e) { // 在Init事件中统一初始化所有需要的控件 _mortgage = (CheckBox)FormView1.FindControl("Mortgage"); _grossProfitPcm = (Literal)FormView1.FindControl("Gross_Profit_PCM"); _rentalPcm = (TextBox)FormView1.FindControl("Rental_PCM"); _reversionaryRateAbr = (TextBox)FormView1.FindControl("Revrsionary_Rate_ABR"); _capitalAmount = (TextBox)FormView1.FindControl("Capital_Amount"); _ddlPropertyID = (DropDownList)FormView1.FindControl("ddlPropertyID"); } protected void GetGPPCM() { // 直接复用类级别的控件引用,无需重复FindControl if (_mortgage.Checked) { decimal currentRate = GetRate() + Convert.ToDecimal(_reversionaryRateAbr.Text); decimal rental = Convert.ToDecimal(_rentalPcm.Text); decimal capital = Convert.ToDecimal(_capitalAmount.Text); decimal monthlyMortgage = ((currentRate / 100) * capital) / 12; _grossProfitPcm.Text = $"£{rental - monthlyMortgage:n}"; } else { _grossProfitPcm.Text = $"£{Convert.ToDecimal(_rentalPcm.Text):n}"; } } }
注意:如果你的FormView存在分页、数据重新绑定的场景,需要在FormView1_DataBound事件中重新初始化控件引用——因为FormView每次绑定数据后,内部控件会被重新实例化,之前的引用会失效:
protected void FormView1_DataBound(object sender, EventArgs e) { // 重新获取控件引用 _mortgage = (CheckBox)FormView1.FindControl("Mortgage"); _grossProfitPcm = (Literal)FormView1.FindControl("Gross_Profit_PCM"); // 其他控件同理... }
方案二:使用延迟加载属性(按需初始化)
如果部分控件并非所有方法都会用到,可以用延迟加载的属性,仅在第一次访问控件时执行FindControl,避免不必要的性能开销。
代码示例:
public partial class WebForm1 : System.Web.UI.Page { private CheckBox _mortgage; public CheckBox Mortgage { get { if (_mortgage == null) { _mortgage = (CheckBox)FormView1.FindControl("Mortgage"); } return _mortgage; } } private Literal _grossProfitPcm; public Literal GrossProfitPcm { get { if (_grossProfitPcm == null) { _grossProfitPcm = (Literal)FormView1.FindControl("Gross_Profit_PCM"); } return _grossProfitPcm; } } // 其他控件同理实现延迟加载属性... protected void GetGPPCM() { if (Mortgage.Checked) { // 直接使用属性即可,自动完成初始化 decimal currentRate = GetRate() + Convert.ToDecimal(ReversionaryRateAbr.Text); GrossProfitPcm.Text = $"£{Convert.ToDecimal(RentalPcm.Text) - (((currentRate / 100) * Convert.ToDecimal(CapitalAmount.Text)) / 12):n}"; } else { GrossProfitPcm.Text = $"£{Convert.ToDecimal(RentalPcm.Text):n}"; } } }
这种方式同样需要注意FormView数据绑定后的引用失效问题,可在DataBound事件中将对应私有字段置为null,下次访问属性时会重新获取最新的控件引用。
内容的提问来源于stack exchange,提问作者mattdean66
相关产品推荐
相关产品推荐

