C# 动态添加的ImageButton命令事件在第二次单击之前不会触发

C# 动态添加的ImageButton命令事件在第二次单击之前不会触发,c#,asp.net,.net,page-lifecycle,C#,Asp.net,.net,Page Lifecycle,我有一个动态添加ImageButtons的页面。我首先设置按钮的OnClientClick,以简单地显示放大的图像弹出窗口,并返回false,表示不回发 我在页面上有一个设置“主图像”的按钮,因此当单击此按钮时,我会设置一个名为\u IsSettingPrimaryPhotoMode=true的属性,调用函数重新创建ImageButtons,并且在创建ImageButtons时,如果此属性为true,而不是在客户端单击时添加,我连接了一个CommandEventHandler,这样我就可以通过读

我有一个动态添加ImageButtons的页面。我首先设置按钮的
OnClientClick
,以简单地显示放大的图像弹出窗口,并返回false,表示不回发

我在页面上有一个设置“主图像”的按钮,因此当单击此按钮时,我会设置一个名为
\u IsSettingPrimaryPhotoMode=true
的属性,调用函数重新创建ImageButtons,并且在创建ImageButtons时,如果此属性为true,而不是在客户端单击时添加
,我连接了一个
CommandEventHandler
,这样我就可以通过读取
CommandArgument
来判断单击了哪个按钮

问题是,事件处理程序不会在第一次单击图像时启动,而只会在第二次单击后启动。我还将代码从
Page\u Load
移动到
OnInit
,并在每次回发时加载图像按钮

我将
\u IsSettingPrimaryPhotoMode
保存到
会话中

private bool _IsSettingPrimaryPhotoMode {
    get {
        bool result = false;

        if(Session[ConstantsWeb.Session.IS_DELETE_IMAGE_MODE] != null) {
            result = Convert.ToBoolean(Session[ConstantsWeb.Session.IS_SETTING_PRIMARY_IMAGE_MODE]);
        }

        return result;
    }
    set {
        Session[ConstantsWeb.Session.IS_SETTING_PRIMARY_IMAGE_MODE] = value;
    }
}
这一页在上面

protected override void OnInit(EventArgs e) {
    base.OnInit(e);

        if(!IsPostBack) {
            _IsSettingPrimaryPhotoMode = false;
        }

        _LoadGalleryImages();
    }
}
LoadGalleryImages方法

private void _LoadGalleryImages() {
    PhotoGalleryImageCollection images = PhotoGalleryImages.GetPhotoGalleryImages();

    foreach(PhotoGalleryImage image in images) {
        ImageButton displayImage = new ImageButton();
        Panel panel = new Panel();
        panelPhotoContainer.Controls.Add(panel);
        displayImage.ImageUrl = "some URL";

        if(!_IsSettingPrimaryPhotoMode) {
            displayImage.OnClientClick = "showPopup(); return false;";
        }
        else {
            displayImage.Command += new CommandEventHandler(displayImage_Command);
            displayImage.CommandName = "ImageButton" + image.PhotoGalleryImageId.ToString();
            displayImage.CommandArgument = image.PhotoGalleryImageId.ToString();
        }

        panel.Controls.Add(displayImage);
    }
}
btnSetPrimaryPhoto_单击

protected void btnSetPrimaryPhoto_Click(object sender, EventArgs e) {
    // if I don't call this, duplicate controls will be added since they were added
    // from OnInit calling _LoadGalleryImages();
    panelPhotoContainer.Controls.Clear();
    _IsSettingPrimaryPhotoMode = true;
    // reload since _IsSettingPrimaryPhotoMode has now changed
    _LoadGalleryImages();
}

我做错了什么?

它必须与初始事件wireup相关,因为问题只在第一次发生。这段时间的不同之处在于_LoadGalleryImages被调用了两次(一次在init中,一次在button click事件处理程序中),因此我认为当您清除容器面板并再次在按钮的click处理程序中调用_LoadGalleryImages时,那里的某些内容没有得到清理

为什么不试试这个替代方案: 每个页面周期仅调用LoadImageGalleries一次(在init中)

与在同一回发中(在button click事件中)清除控件并再次调用LoadGalleryImage不同,在button click上调用一个方法,该方法迭代调用LoadGalleryImage时已创建的图像控件并调整它们:

1) 卸下onclientclick(将其清除)


2) 附加事件。

我想问题可能是因为您没有设置动态创建控件的
ID
s。这是非常重要的,因为它用于启动后返回事件的过程。每个控件的
ID
值应该是常量,并且在回发之间不会改变

您可以尝试修改
\u LoadGalleryImages()
方法,如下所示:

private void _LoadGalleryImages() {
    PhotoGalleryImageCollection images = PhotoGalleryImages.GetPhotoGalleryImages();

    int imageCtrlCounter = 0;
    foreach(PhotoGalleryImage image in images) {
        ImageButton displayImage = new ImageButton() { ID = String.Format("myDisplayImage{0}", imageCtrlCounter) };
        Panel panel = new Panel();
        panelPhotoContainer.Controls.Add(panel);
        displayImage.ImageUrl = "some URL";

        if(!_IsSettingPrimaryPhotoMode) {
            displayImage.OnClientClick = "showPopup(); return false;";
        }
        else {
            displayImage.Command += new CommandEventHandler(displayImage_Command);
            displayImage.CommandName = "ImageButton" + image.PhotoGalleryImageId.ToString();
            displayImage.CommandArgument = image.PhotoGalleryImageId.ToString();
        }

        panel.Controls.Add(displayImage);
        imageCtrlCounter++;
    }
}
@斯旺尼
事实上,在我仔细考虑之后,你的方法确实奏效了。我现在确实在每个OnInit上调用LoadGalleryImage。我意识到这是许多可以合并的重复代码

新加载的GalleryImage



我按照您的建议添加了一个新方法来查找控件,因为它们已经在OnInit中创建,我只需要在单击按钮并清除OnClientClick后查找它们。

private void _LoadSelectPrimaryImages() {
    PhotoGalleryImageCollection images = PhotoGalleryImages.GetPhotoGalleryImages();

    foreach(PhotoGalleryImage image in images) {
        Control control = panelPhotoContainer.FindControl(string.Format("ImageButton{0}", image.PhotoGalleryImageId));

        if(control != null) {
            ImageButton displayImage = (ImageButton)control;
            displayImage.OnClientClick = "";
        }
    }
}


我还有一个“取消”按钮,可以将图像按钮恢复到以前显示弹出窗口的方式。

private void _ResetGalleryImages() {
    PhotoGalleryImageCollection images = PhotoGalleryImages.GetPhotoGalleryImages(_photoGalleryId, false, true);

    foreach(PhotoGalleryImage image in images) {
        Control control = panelPhotoContainer.FindControl(string.Format("ImageButton{0}", image.PhotoGalleryImageId));

        if(control != null) {
            ImageButton displayImage = (ImageButton)control;
            displayImage.ImageUrl = "Original URL";
            displayImage.OnClientClick = "showPopup(); return false;";
        }
    }
}


protected void btnCancelSetPrimaryPhoto_Click(object sender, EventArgs e) {
    _IsSettingPrimaryPhotoMode = false;
    _ResetGalleryImages();
}
然后单击两个页面按钮

protected void btnSetPrimaryPhoto_Click(object sender, EventArgs e) {
    _IsSettingPrimaryPhotoMode = true;
    _LoadSelectPrimaryImages();
}


protected void btnCancelSetPrimaryPhoto_Click(object sender, EventArgs e) {
    _IsSettingPrimaryPhotoMode = false;
    _ResetGalleryImages();
}


有人在早些时候的回复中说…看起来响应已被删除…以清除LoadGallery图像中的控件,例如:

private void _LoadGalleryImages() {
    panelPhotoContainer.Controls.Clear();
    PhotoGalleryImageCollection images = PhotoGalleryImages.GetPhotoGalleryImages();

    foreach(PhotoGalleryImage image in images) {
        ImageButton displayImage = new ImageButton();
        Panel panel = new Panel();
        panelPhotoContainer.Controls.Add(panel);
        displayImage.ImageUrl = "some URL";

        if(!_IsSettingPrimaryPhotoMode) {
            displayImage.OnClientClick = "showPopup(); return false;";
        }
        else {
            displayImage.Command += new CommandEventHandler(displayImage_Command);
            displayImage.CommandName = "ImageButton" + image.PhotoGalleryImageId.ToString();
            displayImage.CommandArgument = image.PhotoGalleryImageId.ToString();
        }

        panel.Controls.Add(displayImage);
    }
}


protected void btnCancelSetPrimaryPhoto_Click(object sender, EventArgs e) {
    _IsSettingPrimaryPhotoMode = false;
    _ResetGalleryImages();
}

这也行,但我认为这可能比你的方法效率更低,@swannee。谢谢

同时尝试添加此代码,看看它是否能纠正您的问题displayImage.Command-=newcommandeventhandler(displayImage_命令);为什么要在按钮单击和另一个事件中调用_LoadGalleryImages()?我认为这不起作用,因为控件是动态添加的。我尝试遍历页面控件,但它们不存在,因为它们是在OnInit中的if(!IsPostBack){}上添加的,但在单击页面按钮后就不存在了。我认为有必要总是在OnInit中调用_loadGalleryImage,这样每次DOM和页面状态都是相同的。问题是我没有向控件添加ID。不确定您是否理解我的响应,我不是说只调用它一次……我是说每个页面周期(在init中)只调用它一次。但只要修复有效……太好了!我现在明白你的意思了。在答案中看到我的解决方案。我不知道我没有足够的声誉来回答我自己的问题而不等待8个小时。请稍后查看我的解决方案。有趣的是,好的,我将等待答案。问题是没有设置ID。这是问题的一部分,但@swannee的解决方案是完整的答案,因此我标记了他的答案,但单击您的答案是有帮助的。哦,我明白了,我看不到对我的答案的任何赞成票(不过,可能会有一些延迟)。不管怎么说,你修好了就好了:)。@Lucas:我本来会给你一次撞击,但我今天已经把我的撞击量最大了……明天我会给你一次。@swannee:谢谢,因为你提到的事情帮助解决了这个问题,我也给了你一次投票:)。