I am using a DropDownList to let a user select a form template. The user then posts back to the server and the user controls from the template are dynamically rendered to the page. Once the user fills in the form and clicks save, the ViewState for the user controls are lost and values are empty.
Page Controls
<air:CreateEditForm ID="CreateEditForm" runat="server" />
<asp:PlaceHolder ID="phDynamicControls" runat="server" />
<p>
<asp:Button ID="btnCreate" runat="server" Text="Create" OnClick="btnCreate_Click" CssClass="action-button" />
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" CssClass="action-button" Visible="false" />
<asp:HyperLink ID="linkCancel" runat="server" Text="Cancel" NavigateUrl="Index.aspx" CssClass="action-button" />
</p>
Page Code
protected void btnCreate_Click(object sender, EventArgs e)
{
CreateDynamicSteps();
}
private void CreateDynamicSteps()
{
foreach (WorkflowTemplate workflowTemplate in template.WorkflowTemplates)
{
foreach (WorkflowTemplateStep workflowStep in workflowTemplate.WorkflowTemplateSteps)
{
if (workflowStep.SubSteps.Count > 0)
{
foreach (WorkflowTemplateStep workflowSubStep in workflowStep.SubSteps)
{
if (workflowSubStep.WhoIsDynamic)
{
dynamicSteps.Add(workflowSubStep);
}
}
}
else if (workflowStep.WhoIsDynamic)
{
dynamicSteps.Add(workflowStep);
}
}
}
// removed for brevity
foreach (WorkflowTemplateStep dynamicStep in dynamicSteps)
{
PersonSelectorDialog personSelector = (PersonSelectorDialog)LoadControl("~/Pages/UserControls/PersonSelectorDialog.ascx");
personSelector.ClientIDMode = System.Web.UI.ClientIDMode.Static;
personSelector.LabelID = "lbl" + dynamicStep.ID;
personSelector.Label = dynamicStep.Name + " Selector";
DynamicPersonSelectorDialogs.Add(personSelector);
}
// removed for brevity
}
private void LoadControls()
{
foreach (PersonSelectorDialog personSelector in DynamicPersonSelectorDialogs)
{
Label title = new Label();
title.ID = personSelector.LabelID;
title.ClientIDMode = System.Web.UI.ClientIDMode.Static;
title.Text = personSelector.Label;
phDynamicControls.Controls.Add(title);
phDynamicControls.Controls.Add(personSelector);
}
}
When the user selects the form template from the dropdown and the postback is triggered, that value needs to be retained somewhere because when you perform the second postback you need to load the usercontrol again from the first postback.
Related
I'm trying to display textboxes based on the checkboxlist items that the user has selected. I have 15 items in my checkboxlist with a textbox which corresponds to each when selected. I've made this code but I am unsure how to proceed. My goal is to look through the items in my checkboxlist and whenever it finds a selected item, it will make visible the div which displays the textbox. The textbox will have almost the same name as it's check box list equivalent. My problem is Im not quite sure how to take that value and making it so that it looks for the textbox control with the same name and display.
This is what I have so far:
{
foreach(ListItem item in cblReasonSeekingServices.Items)
{
if (item.Selected == true)
{
string strControlName = item.Value;
string strSpaceRemoved = Regex.Replace(strControlName, " ", "");
((TextBox)FindControl("pnl" + strSpaceRemoved)).Visible = true;
}
}
}
EDIT: I'm able to run the code now without any error messages however, the textbox control does not display. Am I missing anything?
foreach(ListItem item in cblReasonSeekingServices.Items)
{
if (item.Selected == true)
{
string strControlName = item.Value;
string strSpaceRemoved = Regex.Replace(strControlName, " ", "");
string test = ("tb" + strSpaceRemoved);
TextBox tBox = this.Master.FindControl("body").FindControl("tbBehavioralDifficulties") as TextBox;
tBox.Visible = true;
}
Hum, ok, say we have 5 text box, and then
So, say this:
<div style="float:left;width:20%">
<asp:CheckBoxList ID="CheckBoxList1" runat="server">
</asp:CheckBoxList>
</div>
<div style="float:left;width:20%">
<asp:TextBox ID="TextBox1" runat="server" Text="Text1"> </asp:TextBox> <br />
<asp:TextBox ID="TextBox2" runat="server" Text="Text2"> </asp:TextBox> <br />
<asp:TextBox ID="TextBox3" runat="server" Text="Text3"> </asp:TextBox> <br />
<asp:TextBox ID="TextBox4" runat="server" Text="Text4"> </asp:TextBox> <br />
<asp:TextBox ID="TextBox5" runat="server" Text="Text5"> </asp:TextBox> <br />
</div>
<div style="clear:both;height:20px">
</div>
<asp:Button ID="Button1" runat="server" Text="Show selected" OnClick="Button1_Click" />
And code behind is this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
for (int i = 1; i <= 5; i++)
{
ListItem OneItem = new ListItem("Choice #" + i, i.ToString());
CheckBoxList1.Items.Add(OneItem);
// hide the text box
string sTbox = "TextBox" + i;
TextBox Tbox = Page.FindControl(sTbox) as TextBox;
Tbox.Visible = false;
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
foreach (ListItem Choice in CheckBoxList1.Items)
{
string sTbox = "TextBox" + Choice.Value;
TextBox Tbox = Page.FindControl(sTbox) as TextBox;
Tbox.Visible = Choice.Selected;
}
}
So, we get this then - select a few check box, hit button:
Please consider this scenario:
I have a simple page and I want to log all controls causing postback. I create this simple page. It contains a grid to show some URLs and when user click on an icon a new tab should open:
<form id="form1" runat="server">
<div>
<table style="width: 100%;">
<tr>
<td style="background-color: #b7ffbb; text-align: center;" colspan="2">
<asp:Button ID="Button3" runat="server" Text="Click Me First" Height="55px" OnClick="Button3_Click" />
</td>
</tr>
<tr>
<td style="background-color: #f1d8fe; text-align: center;" colspan="2">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" BackColor="White" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundField DataField="SiteAddress" HeaderText="Address" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="ImageButton1" ImageUrl="~/download.png" runat="server" CommandArgument='<%# Eval("SiteAddress") %>' CommandName="GoTo" Height="32px" Width="32px" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
</table>
</div>
</form>
and code behind:
public partial class WebForm2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button3_Click(object sender, EventArgs e)
{
List<Address> Addresses = new List<Address>()
{
new Address(){ SiteAddress = "https://google.com" },
new Address(){ SiteAddress = "https://yahoo.com" },
new Address(){ SiteAddress = "https://stackoverflow.com" },
new Address(){ SiteAddress = "https://learn.microsoft.com/}" }
};
GridView1.DataSource = Addresses;
GridView1.DataBind();
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "MyScript", "window.open('" + e.CommandArgument.ToString() + "', '_blank')", true);
}
}
class Address
{
public string SiteAddress { get; set; }
}
every thing is fine till here. Now I create a base class for all of my pages and add below codes for finding postback control:
public class MyPageBaseClass : Page
{
protected override void OnInit(EventArgs e)
{
if (!IsPostBack)
{
}
else
{
var ControlId = GetPostBackControlName(); <------
//Log ControlId
}
base.OnInit(e);
}
private string GetPostBackControlName()
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = Page.FindControl(ctrlname);
}
else
{
foreach (string ctl in Page.Request.Form)
{
Control c;
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
string ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = Page.FindControl(ctrlStr);
}
else
{
c = Page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
if (control != null)
return control.ID;
else
return string.Empty;
}
}
and change this line:
public partial class WebForm2 : MyPageBaseClass
Now when I click on icons grid view disappears...(STRANGE...) and nothing happened. When I comment specified line then every thing will be fine...(STRANGE...).
In GetPostBackControlName nothings changed to Request but I don't know why this happened. I checked and I see if I haven't RegisterStartupScript in click event every thing is fine. Please help we to solve this problem.
Thanks
when I click on icons grid view disappears...
ASP.Net page class object instances only live long enough to serve one HTTP request, and each HTTP request rebuilds the entire page by default.
Every time you do a postback, you have a new HTTP request and therefore a new page class object instance and a completely new HTML DOM in the browser. Any work you've done for a previous instance of the page class — such as bind a list of addresses to a grid — no longer exists.
You could fix this by also rebuilding your grid code on each postback, but what I'd really do is skip the whole "RegisterStartupScript" mess and instead make the grid links open the window directly, without a postback at all.
The problem is related to OnInit event. I replaced it with OnPreLoad and every things is fine now.
For search engines: OnInit event has conflict with RegisterStartupScript
Actually, I am Creating 1 TextBox on Pageload and adding that TextBox to Panel.
Now, I have a LinkButton like Add Another.
I am entering Text in that TextBox and if needed I need to Create New TextBox,by clicking Add Another LinkButton.
Actually, I am able to get the count and recreate the TextBoxes.
But,the Problem is that, My Entered text in the Previously Generated Textboxes is Missing.
Can Anyone,Suggest me a solution for this?
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (!IsPostBack)
{
for (int i = 0; i < 5; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < 5; j++)
{
TableCell cell = new TableCell();
TextBox tb = new TextBox();
tb.ID = "TextBoxRow_" + i + "Col_" + j;
cell.Controls.Add(tb);
row.Cells.Add(cell);
}
Table1.Rows.Add(row);
}
}
}
catch (Exception ex)
{
throw;
}
}
This is a Sample Code, the same code is written in Button_Click Also
protected void ASPxButton1_Click(object sender, EventArgs e)
{
int k = Table1.Controls.Count;
}
I am getting a Count=0 on Button_Click.
All you need to do is to re-instantiate / reinitialize dynamic controls before or within page load event each and every time during postback and add this control to page / forms / placeholders. Then, the posted data will automatically be assigned to the control by calling the LoadPostData method by the parent control.
check the article and how to write code for dynamic control -
How to maintain dynamic control events, data during postback in asp.net
When using dynamic controls, you must remember that they will exist only until the next postback.ASP.NET will not re-create a dynamically added control. If you need to re-create a control multiple times, you should perform the control creation in the PageLoad event handler ( As currently you are just creating only for first time the TextBox using Condition: !IsPostabck ). This has the additional benefit of allowing you to use view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the PageLoad event, ASP.NET will apply any view state information that it has after the PageLoad event handler ends.
So, Remove the Condition: !IsPostback, So that each time the page Loads, The TextBox control is also created. You will also see the State of Text box saved after PageLoad handler completes. [ Obviously you have not disabled ViewState!!! ]
Example:
protected void Page_Load(object sender, EventArgs e)
{
TextBox txtBox = new TextBox();
// Assign some text and an ID so you can retrieve it later.
txtBox.ID = "newButton";
PlaceHolder1.Controls.Add(txtBox);
}
Now after running it, type anything in text box and see what happens when you click any button that causes postback. The Text Box still has maintained its State!!!
The dynamically generated control do not maintain state. You have to maintain it at your own. You can use some hidden field to keep the state of controls, which will be used on server side to extract the state. Asp.net uses hidden field to maintain the state between requests, you can see __VIEWSTATE in the source.
In ASP.NET pages, the view state represents the state of the page when
it was last processed on the server. It's used to build a call context
and retain values across two successive requests for the same page. By
default, the state is persisted on the client using a hidden field
added to the page and is restored on the server before the page
request is processed. The view state travels back and forth with the
page itself, but does not represent or contain any information that's
relevant to client-side page display, Reference.
Just remove this line
if (!IsPostBack)
This is My final answer after working a lot with Dynamic Controls
.aspx
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="text-align: center">
<div style="background-color: Aqua; width: 250px;">
<br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="myPlaceHolder"></asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddTextBox" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<br />
</div>
<br />
<asp:Button ID="btnAddTextBox" runat="server" Text="Add TextBox" OnClick="btnAddTextBox_Click" />
<br /><br />
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:Button runat="server" ID="MyButton" Text="Get Values." OnClick="MyButton_Click" />
<br /><br />
<asp:Label runat="server" ID="MyLabel"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
.aspx.cs
static int myCount = 0;
private TextBox[] dynamicTextBoxes;
protected void Page_PreInit(object sender, EventArgs e)
{
Control myControl = GetPostBackControl(this.Page);
if ((myControl != null))
{
if ((myControl.ClientID.ToString() == "btnAddTextBox"))
{
myCount = myCount + 1;
}
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
dynamicTextBoxes = new TextBox[myCount];
int i;
for (i = 0; i < myCount; i += 1)
{
TextBox textBox = new TextBox();
textBox.ID = "myTextBox" + i.ToString();
myPlaceHolder.Controls.Add(textBox);
dynamicTextBoxes[i] = textBox;
LiteralControl literalBreak = new LiteralControl("<br />");
myPlaceHolder.Controls.Add(literalBreak);
}
}
protected void btnAddTextBox_Click(object sender, EventArgs e)
{
// Handled in preInit due to event sequencing.
}
protected void MyButton_Click(object sender, EventArgs e)
{
MyLabel.Text = "";
foreach (TextBox tb in dynamicTextBoxes)
{
MyLabel.Text += tb.Text + " :: ";
}
}
public static Control GetPostBackControl(Page thePage)
{
Control myControl = null;
string ctrlName = thePage.Request.Params.Get("__EVENTTARGET");
if (((ctrlName != null) & (ctrlName != string.Empty)))
{
myControl = thePage.FindControl(ctrlName);
}
else
{
foreach (string Item in thePage.Request.Form)
{
Control c = thePage.FindControl(Item);
if (((c) is System.Web.UI.WebControls.Button))
{
myControl = c;
}
}
}
return myControl;
}
When you are working with dynamic controls they will not able to maintain its state during postback and their data lost Cause they dont have any viewstate to maintain their data.
You only need to maintain the created controls data into ViewState
dynamically and loads the data into page at the time of postback and you
done.
public Dictionary<Guid, string> UcList
{
get { return ViewState["MyUcIds"] != null ? (Dictionary<Guid, string>)ViewState["MyUcIds"] : new Dictionary<Guid, string>(); }
set { ViewState["MyUcIds"] = value; }
}
public void InitializeUC()
{
int index = 1;
foreach (var item in UcList)
{
var myUc = (UserControls_uc_MyUserControl)LoadControl("~/UserControls/uc_MyUserControl.ascx");
myUc.ID = item.Value;
pnlMyUC.Controls.AddAt(index, myUc);
index++;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadControl();
else
InitializeUC();
}
Actually, I have used Javascript for accomplishing my task.
and it goes like this :
<form id="form1" runat="server" enctype="multipart/form-data" method="post">
<span style="font-family: Arial">Click to add files</span>
<input id="Button1" type="button" value="add" onclick="AddFileUpload()" />
<br />
<br />
<div id="FileUploadContainer">
<!--FileUpload Controls will be added here -->
</div>
<asp:HiddenField ID="HdFirst1" runat="server" Value="" />
<br />
<asp:Button ID="btnUpload" runat="server" Text="Upload" OnClick="btnUpload_Click" />
</form>
Script :
<script type="text/javascript">
var counter = 0;
function AddFileUpload() {
var div = document.createElement('DIV');
div.innerHTML = '<input id="file' + counter + '"name = "file' + counter + '"type="text"/><input id="file' + counter + '" name = "file' + counter + '" type="file" /><input id="Button' + counter + '" type="button" value="Remove" onclick = "RemoveFileUpload(this)" />';
document.getElementById("FileUploadContainer").appendChild(div);
counter++;
}
function RemoveFileUpload(div) {
document.getElementById("FileUploadContainer").removeChild(div.parentNode);
}
function mydetails(div) {
var info;
for (var i = 0; i < counter; i++) {
var dd = document.getElementById('file' + i).value;
info = info + "~" + dd;
}
document.getElementById('<%= HdFirst1.ClientID %>').value = info;
}
</script>
and In the Upload_Click Button :
for (int i = 0; i < Request.Files.Count; i++)
{
string strname = HdFirst1.Value;
string[] txtval = strname.Split('~');
HttpPostedFile PostedFile = Request.Files[i];
if (PostedFile.ContentLength > 0)
{
string FileName = System.IO.Path.GetFileName(PostedFile.FileName);
// string textname=
//PostedFile.SaveAs(Server.MapPath("Files\\") + FileName);
}
}
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
The ASPxGridView stores information about columns in ViewState, but does not save information about column templates. This is made on purpose since templates can be very complex and their serialization makes ViewState very huge.
So, if you create columns with templates at runtime, disable ViewState:
ASPxGridView.EnableViewState="false"
and create columns on every callback:
//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
//}
You used code below:
<Triggers>
<asp:AsyncPostBackTrigger ControlID="mainGrid" />
</Triggers>
According to this article, in asp:AsyncPostBackTrigger If the EventName property is not specified, the DefaultEventAttribute attribute of the control is used to determine the default event. For example, the default event for the Button control is the Click event.
mainGrid control created by GridViewWrapper that it doesn't connected to controls that are in mainGrid.
Updatepanel tries to register async trigger for the mainGrid control which is outside the panel but it can't do it.
solution:
I think solution of this problem is update Updatepanel in ShowImage() method.
I have a payment method repeater that contains a button. We have new button styles that need to be applied. The new button style changes based on a btnMode setting in the database which is set to a string representing a CSS class selector. The CSS works fine.
I put this in the ASPX page:
<asp:Button ID="btnEdit"
runat="server"
ClientIDMode="Static"
CssClass='<%# Eval("btnMode") %>'
Text="edit"
CommandName="ChangePaymentProfile"
CommandArgument='<%# Eval("PaymentSourceId") + "|" + Eval("AuthNetPaymentProfileId")%>' />
In the ASPX.cs
//Command Button Clicked: Change Payment Method
else if (e.CommandName.ToLower().Equals("changepaymentprofile"))
{
hdChangeYN.Value = "Y";
showAddPaymentForm();
//display billing address of selected card
hsParams.Add("CustomerId", User.Identity.Name);
hsParams.Add("PaymentSourceId", strPaymentSourceId);
DataTable dt = DbHelper.GetDataTableSp("234_accountAddress__ByPaySourceId", hsParams);
if (dt.Rows.Count > 0)
{
tbFistName.Text = dt.Rows[0]["FirstName"].ToObjectString();
tbLastName.Text = dt.Rows[0]["LastName"].ToObjectString();
inputAddress1.Text = dt.Rows[0]["Address"].ToObjectString();
inputAddress2.Text = "";
string strCountryCd = dt.Rows[0]["CountryCd"].ToObjectString();
ddlCountry_Update(strCountryCd); //Update Country & State DDL because Country can be a foreign country
ddlCountry.SelectedValue = strCountryCd;
inputCity.Text = dt.Rows[0]["City"].ToObjectString();
ddlState.SelectedValue = dt.Rows[0]["StateProvinceId"].ToObjectString();
inputZipcode.Text = dt.Rows[0]["Zipcode"].ToObjectString();
ddlCardType.SelectedValue = dt.Rows[0]["CardType"].ToObjectString();
}
}
When I load the page in the browser the <%# Eval("btnMode") %> does not get resolved to a value. I see this when I open the inspector:
<input
id="btnEdit"
class="<%# Eval("btnMode") %>"
type="submit"
name="ctl00$ctl00$ContentPlaceHolderFront$ContentPlaceHolderFront$rptList$ctl01$btnPrimary"
value=""
onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$ctl00$ContentPlaceHolderFront$ContentPlaceHolderFront$rptList$ctl01$btnPrimary", "", true, "", "", false, false))" >
It is important to point out that this attribute CommandArgument='<%# Eval("PaymentSourceId") %>' does work, and btnMode does contain valid data.
As I wrote in a comment, not all properties in Asp.Net controls can be databound. CssClass is one that cannot be databound.
To get around this, you can add an OnItemDataBound event handler to the repeater where the Button is. In the event handler you can then user the e.Item.DataItem to get the value you want and set it as the CssClass on the button. Sample code:
<asp:Repeater ID="RepeaterTest" runat="server" OnItemDataBound="RepeaterTest_ItemDataBound">
<ItemTemplate>
<div>
<asp:Button ID="TestButton" runat="server" Text='<%# Eval("someText") %>'/>
</div>
</ItemTemplate>
</asp:Repeater>
and code behind:
protected void Page_Load(object sender, EventArgs e)
{
var testData = Enumerable.Range(1, 10).Select(i => new { someText = "Button " + i.ToString() }).ToList();
RepeaterTest.DataSource = testData;
RepeaterTest.DataBind();
}
protected void RepeaterTest_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
dynamic foo = e.Item.DataItem;
((Button)e.Item.FindControl("TestButton")).CssClass = foo.someText;
}