I've struggled a lot with how to show a modal panel on click on a button inside a grid view.
To context: I have a data row with a string field that can contain a simple text or a base 64 encoded image, so I'm using a custom template to define when to show the raw content or a button "View Image". This image will be opened on a modal panel that should rise up on button click.
This is the Panel I've created as a control (ascx):
<asp:Panel ID="pnlModalOverlay" runat="server" Visible="true" CssClass="Overlay">
<asp:Panel ID="pnlModalMainContent" runat="server" Visible="true" CssClass="ModalWindow">
<div class="WindowTitle">
<asp:Label ID="lbTitle" runat="server" />
</div>
<div class="WindowBody">
<asp:Panel ID="pnlContent" runat="server" Visible="true">
<asp:Image ID="imgContent" runat="server" CssClass="ImageView" />
</asp:Panel>
<div class="Button">
<asp:Button ID="btnOk" runat="server" class="btn btn-default " Text="Close" OnClientClick="loadingPanel.Show();" />
</div>
</div>
</asp:Panel>
</asp:Panel>
And this is the page and ASPxGridView where I wanna use it:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<div style="margin-top: 12px;">
<asp:Button type="button" ID="btnShowImage" AutoPostBack="true" class="btn btn-default navbar-right" Text="Show Image"
runat="server" Style="margin-left: 5px;" OnClientClick="loadingGridPanel.Show();" />
</div>
<!-- Some data filter controls -->
<MyWorkspace:AlertModal ID="alertModal" runat="server" Visible="false" />
<MyWorkspace:ImageModal ID="imageModal" runat="server" Visible="false" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="mainGrid" />
</Triggers>
</asp:UpdatePanel>
<MyWorkspace:GridViewWrapper ID="mainGrid" runat="server" Visible="true" />
Codebihind:
public partial class MyPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
btnShowImage.Click += new EventHandler(ShowImage); // This call works fine
}
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (!IsPostBack)
{
mainGrid.CanEditItems = true;
mainGrid.CustomTemplates.Add(new CustomColumnTemplate { columnName = "Id", template = new LinkColumn(CreateParentLink, "Go to parent") });
mainGrid.CustomTemplates.Add(new CustomColumnTemplate { columnName = "Value", template = new ButtonColumn(ShowImage, "View Image") }); // This one doesn't works
}
}
catch (Exception ex)
{
modalAlerta.Show("Page_Load", ex.Message, false, false, "");
}
}
void ShowImage()
{
modalImagem.Show(); // Set Modal's Visible property to True
// UpdatePanel1.Update(); <-- Tryin' force it to work with no success
}
}
The ButtonColumn template creation:
public class ButtonColumn : System.Web.UI.ITemplate
{
private Action action;
private string controlId;
private string tooltip;
public ButtonColumn(Action onClick, string toolTip)
{
this.action = onClick;
this.controlId= "btnShowImage";
this.tooltip = toolTip;
}
public void InstantiateIn(System.Web.UI.Control container)
{
GridViewDataItemTemplateContainer gridContainer = (GridViewDataItemTemplateContainer)container;
if (System.Text.RegularExpressions.Regex.IsMatch(gridContainer.Text, "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"))
{
ImageButton button = new ImageButton();
button.ID = idControle;
button.ImageUrl = "/Images/html5_badge_64.png";
button.Width = 20;
button.Height = 20;
button.ToolTip = tooltip;
button.Click += (s, a) =>
{
if (onClick != null)
onClick();
};
container.Controls.Add(button);
}
else
{
Label label = new Label()
{
Text = gridContainer.Text,
ToolTip = tooltip
};
container.Controls.Add(label);
}
}
}
The method's call at the click of btnShowImage
button works fine. But when I do the same call by one ImageButton (or button) inside the gridview it doesn't work. Both calls reach the ShowImage method.
Any help would be appreciated. Thank you all.
EDIT 1:
The GridView is encapsulated in GridViewWrapper
(there I build the columns dynamically using a combination of class's properties gotten by reflection and stored metadata), this class have too much code to share here and I do not think it's the reason. Also, I've executed in debug mode and passed thru it step by step every relevant method inside this one.
The column add method:
CustomColumnTemplate customTemplate = CustomTemplates.FirstOrDefault(f => f.columnName == metadata.ColumnIdName);
gridView.Columns.Add(new GridViewDataColumn()
{
FieldName = metadata.ColumnIdName,
VisibleIndex = GetVisibleIndexByColumnIdName(metadata.ColumnIdName),
Caption = metadata.Caption,
Width = new Unit(DefaultColumnWidth, UnitType.Pixel),
DataItemTemplate = customTemplate == null ? null : customTemplate.template
});
I've made sure the ShowImage
method is being hitten, but it behaves like the UpdatePanel1
isn't have been updated