在事件中使用FindControl设置用户控件的属性

3

我有一个用户控件,在页面加载时动态加载:

protected void Page_Load(object sender, EventArgs e)
{
    MyControl ctl = (MyControl)LoadControl(controlPath);
    ctl.ID = "mycontrol";
    this.MyControlPlaceHolder.Controls.Add(ctl);
}

页面前端:

<asp:PlaceHolder runat="server" ID="MyControlPlaceHolder"></asp:PlaceHolder>

我在页面上有一个点击事件,它会触发并提交一个 postback,并调用一个方法,在该方法中我试图查找控件并设置一些属性:

        MyControl ctl = (MyControl)FindControl("mycontrol");
        if (ctl != null){
            ctl.MyProperty = true;
            Response.Write("success");
        }
        else
            Response.Write("fail");

这是在PostBack后写入失败,因此看起来我在查找控件时做错了什么。最好的方法是什么?

编辑:

I switched it to MyControl ctl = (MyControl)this.MyControlPlaceHolder.FindControl("mycontrol");

这使得它能够找到控件,但是当控件在回发后加载时,似乎属性没有设置。


标题中不需要标签,标签系统会处理。请阅读http://meta.stackexchange.com/q/19190获取更多信息。 - Patrick
在每次回传时,您应该始终在Page_init上重新加载用户控件。它们必须在init或preinit期间添加,因为只有这样才能正确捕获和恢复视图状态。 - Ehsan
3个回答

2

您需要使用递归的FindControl实现,因为FindControl只能找到直接子级。您的控件被插入到一个较低级别的命名容器中。这里是MSDN提��的通用FindControlRecurisve的实现:

private Control FindControlRecursive(Control rootControl, string controlID)
{
    if (rootControl.ID == controlID) return rootControl;

    foreach (Control controlToSearch in rootControl.Controls)
    {
        Control controlToReturn = 
            FindControlRecursive(controlToSearch, controlID);
        if (controlToReturn != null) return controlToReturn;
    }
    return null;
}

来自MSDN

或者,如果您只有一个特定的容器,就像在您的示例中:

MyControl ctl =  this.MyControlPlaceHolder.FindControl("mycontrol");

if (ctl != null){
            ctl.MyProperty = true;
            Response.Write("success");
        }
        else
            Response.Write("fail");

ViewState使您的控件具备状态保持功能

public class MyControl:Control
{
   public bool MyProperty
   {
       get 
       {
           return ViewState["my"] != null? (bool) ViewState["my"]: false; 
       }
       set 
       {
           ViewState["my"]  = value;
       }
   }
}

我把它切换到底部部分,现在它正在写入“成功”,但是在回发之后,属性似乎没有被设置。所以它找到了控件,但用户控件加载时好像属性没有被设置。 - maembe
MyControl需要将其MyProperty值存储在其ViewState中,并且您必须在Page_INIT事件(而不是LOAD事件)中将控件插入容器。您的控件的get方法必须读取其ViewState - rene

0
尝试将动态添加控件的代码移到Init而不是Load中。我无法确定,但在Init和Load之间会发生很多事情,如果您的控件不存在或未被识别,可能会引起此类问题。

0

您将控件添加到了占位符的控件集合中。如果您想要查找动态添加的控件,除了确定是哪个控件之外,您还需要从根(可能是页面)开始进行递归搜索,因此,如果您在网上冲浪,您可以找到好的解决方案。

个人而言,我更喜欢具有泛型支持并表示为扩展方法的解决方案,这样您就可以在任何地方使用该解决方案。以下是一些有用的链接

  1. 带泛型的递归查找控件
  2. 通过扩展方法带泛型的递归查找控件
  3. 通过扩展方法和linq支持/示例带泛型的递归查找控件

希望这能帮到您


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接