I have the following code. I am trying to display a message when a file is to big. My problem is that the message is displayed only when I press the submit button twice. It is always one step behind. How can i fix that?
What I am doing is save a viewstate when the file is to big, and when the page loads, set the visibility of the label to true or false, depending on the file size.
I am guessing the load happens before my check, so is there another method i can use instead of Page_Load or can I do something else to make it work?
<asp:UpdatePanel ID="updatePanel" runat="server">
<ContentTemplate>
<div>
<div class="balClear">
<asp:FileUpload ID="uploader" CssClass="balUploader" runat="server"/>
<asp:ImageButton ID="uploaderEraser" CssClass="balUploaderCleaner" OnClick="uploaderEraser_Click" runat="server" Width="25" Height="25" />
</div>
<div style="clear:both">
<asp:Label ID="fileSizeError" runat="server" ForeColor="Red">The file you are trying to upload is too big. The maximul file size is 2MB.</asp:Label>
</div>
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="uploaderEraser" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="submit" runat="server" Text="Submit" OnClick="submit_Click" />
cs code:
string groupURL = "~/Uploads/Group/";
string privateURL = "~/Uploads/Private/";
int maximumMB = 2;
string folderURL
{
get { return IsGroup == true ? groupURL : privateURL; }
}
public bool IsGroup
{
get { return ViewState["balUploader_IsGroup"] == null ? false : (bool)ViewState["balUploader_IsGroup"]; }
set { ViewState["balUploader_IsGroup"] = value; }
}
bool FileTooBig
{
get { return ViewState["balUploader_FileTooBig"] == null ? false : (bool)ViewState["balUploader_FileTooBig"]; }
set { ViewState["balUploader_FileTooBig"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (FileTooBig == true)
{
fileSizeError.Visible = true;
}
else
{
fileSizeError.Visible = false;
}
}
public void StoreFile()
{
if (uploader.HasFile)
{
if (uploader.FileBytes.Length / 1024 / 1024 < maximumMB)
{
FileTooBig = false;
string fileName = Path.GetFileName(uploader.FileName);
uploader.SaveAs(Server.MapPath(folderURL) + fileName);
}
else
{
FileTooBig = true;
}
}
else
{
FileTooBig = false;
}
}
protected void submit_Click(object sender, EventArgs e)
{
StoreFile();
}
Basically, what is happening is that the submit_Click event is being fired after the Page_Load. That is due to the ASP.NET page life cycle.
The basic order of events is the following:
1 - Init
2 - Load (Page_Load is fired)
3 - Control Events (submit_Click is fired)
4 - Load Complete
5 - Pre_Render
6 - Render
You have two options here.
1 - Use the LoadComplete handler:
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
//Label Logic here
}
2 - Use the OnPreRender:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//Label Logic here
}
Related
My application consists of a web form that someone may be pulling some information in. When that occurs, I'm loading a user control more than once, based on content, that has an ImageButton on it.
Since this is being loaded after page is already loaded, how can I get the click events to work properly. Since click events are required to be set during page_load.
Example Scenario:
Main.aspx
<form id="form1" runat="server">
<div>
<asp:Button ID="clicker" runat="server" Text="Click Me" />
<asp:PlaceHolder ID="PHwfuc" runat="server"></asp:PlaceHolder>
<asp:Label runat="server" ID="ResponseMessage"></asp:Label>
</div>
</form>
Main.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
clicker.Click += new EventHandler(this.ButClick);
}
protected void ButClick(object sender, EventArgs e)
{
PlaceHolder placeHolder = new PlaceHolder();
for (int i = 0; i < 2; i++)
{
WFUC1 test = LoadControl("~/WebFormUserControl/WFUC1.ascx") as WFUC1;
test.Ident = i;
placeHolder.Controls.Add(test);
}
PHwfuc.Controls.Add(placeHolder);
}
WFUC1.ascx
<asp:PlaceHolder runat="server" ID="DelAddrBtn"></asp:PlaceHolder>
<asp:Label runat="server" ID="ResponseMessage"></asp:Label>
<br />
WFUC1.ascx.cs
public WFUC1()
{
TrashIcon = new ImageButton
{
AlternateText = "Delete Address",
ImageUrl = "/images/trash.png",
ToolTip = "Delete Address",
};
TrashIcon.Style.Add("cursor", "pointer");
TrashIcon.Style.Add("width", "24px");
}
private ImageButton TrashIcon { get; set; }
public int Ident { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
TrashIcon.ID = $"Delete_{Ident}";
TrashIcon.Click += new ImageClickEventHandler(this.TrashIcon_Click);
DelAddrBtn.Controls.Add(TrashIcon);
}
protected void TrashIcon_Click(object sender, ImageClickEventArgs e)
{
ResponseMessage.Text = $"Use Control Got it. {Ident}";
}
EDIT For Rango
WFUC1.ascx
<asp:ImageButton runat="server" ID="TrashIcon" ImageUrl = "/images/trash.png" ToolTip = "Delete Address" OnClick="TrashIcon_Click" />
<asp:Label runat="server" ID="ResponseMessage"></asp:Label>
<br />
WFUC1.ascx.cs
public partial class WFUC1 : System.Web.UI.UserControl
{
public int Ident { get; set; }
protected void TrashIcon_Click(object sender, ImageClickEventArgs e)
{
ResponseMessage.Text = $"Use Control Got it. {Ident}";
}
}
Seems, I have to reload all the controls on the main again to get the click event to execute. I accidentally made this work.
Below Project Visual Studio 2017 - No binaries, except for one image and the rest is only project code.
Main.aspx
<form id="form1" runat="server">
<asp:Button ID="clicker" runat="server" Text="Click Me" />
<asp:PlaceHolder ID="PHwfuc" runat="server"></asp:PlaceHolder>
<asp:Label runat="server" ID="ResponseMessage"></asp:Label>
</form>
Main.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
clicker.Click += new EventHandler(this.ButClick);
if(ViewState["ButClick"] != null)
LoadData();
}
protected void ButClick(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
PlaceHolder placeHolder = new PlaceHolder();
for (int i = 0; i < 2; i++)
{
WFUC1 test = LoadControl("~/WebFormUserControl/WFUC1.ascx") as WFUC1;
test.Ident = i;
placeHolder.Controls.Add(test);
}
PHwfuc.Controls.Add(placeHolder);
ViewState["ButClick"] = true;
}
WFUC1.ascx
<asp:ImageButton runat="server" ID="TrashIcon" ImageUrl = "/images/trash.png" ToolTip = "Delete Address" OnClick="TrashIcon_Click" />
<br />
<asp:Label runat="server" ID="ResponseMessage"></asp:Label>
WFUC1.ascx
public int Ident { get; set; }
public void TrashIcon_Click(object sender, ImageClickEventArgs e)
{
ResponseMessage.Text = $"Use Control Got it. {Ident}";
}
I want to refresh a user control in UpdatePanel, but I would also like to refresh it with different property values.
<asp:UpdatePanel runat=server ID=up1>
<Triggers>
<asp:AsyncPostBackTrigger controlid="but01" eventname="Click" />
</Triggers>
<ContentTemplate>
<asp:Button runat="server" Text="Test" ID="but01" />
<UC:Uc runat=server ID="Uc1" />
</ContentTemplate>
</asp:UpdatePanel>
Codebehind for but01 click is
void but01_Click(object sender, EventArgs e)
{
this.Uc1.ID = 1;
this.Uc1.Length = 50;
}
I tested this code, and the user control is being refreshed, but new values ID=1, Length=50 are not applied.
Control code behind is rather simple
namespace Admin.Web.Controls
{
public partial class Uc1 : System.Web.UI.UserControl
{
private string p_to;
private string p_from;
private string p_subject;
private string p_body;
private string p_priority;
}
protected void Page_Load(object sender, EventArgs e)
{
this.txtFrom.Text = p_from;
this.txtTo.Text = p_to;
this.txtSubject.Text = p_subject;
this.txtBody.Text = p_body;
}
public string Subject
{
get
{
return p_subject;
}
set
{
p_subject = value;
}
}
public string From
{
get
{
return p_from;
}
set
{
p_from = value;
}
}
public string To
{
get
{
return p_to;
}
set
{
p_to = value;
}
}
public string Body
{
get
{
return p_body;
}
set
{
p_body = value;
}
}
}
ascx header is
<%# Control Language="c#" Inherits="Admin.Web.Controls.Uc1" AutoEventWireup="true" Codebehind="Uc1.ascx.cs" %>
When I initiate user control from aspx page during page load, everything is ok. On postback from control panel, user control is refreshed (checked with Label + time), but no values are passed to user control.
Remove Triggers tag
http://msdn.microsoft.com/en-us/library/Bb399001(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
OR
Move asp:Button to outside of UpdatePanel.
http://msdn.microsoft.com/en-us/library/Bb399001(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-5
Update:
Please make the setter and getter of the control as -
public string Subject
{
get { return txtSubject.Text; }
set { txtSubject.Text = value; }
}
i'm trying to do this assigning an method to the event on the checkbox tag like this:
OnCheckedChanged="ShowDiv"
However, i'm not succesfull at all. How to do it? Here's my method:
public void ShowDiv(object sender, System.EventArgs e)
{
var div = FindControl("ListaEmOutrosDocumentos") as HtmlGenericControl;
var checkbox = FindControl("Principal") as CheckBox;
if(checkbox.Checked == true)
{
div.Style.Clear();
div.Style.Add("display","block");
}
else
{
div.Style.Clear();
div.Style.Add("display","none");
}
}
You might consider using an ASP.NET Panel control instead of a div. That will have a Visible property that you can set.
Quick way using server side code only
Aspx
<div id="myDiv" runat="server" style="height:200px;width:100px;background-color:Blue"></div>
<asp:CheckBox ID="chkShowHideDiv" runat="server" AutoPostBack="True"
oncheckedchanged="chkShowHideDiv_CheckedChanged" Text="Hide Div" />
Code behind
protected void chkShowHideDiv_CheckedChanged(object sender, EventArgs e)
{
myDiv.Visible = chkShowHideDiv.Checked ? false : true;
}
I did this and it worked.
<div id="ListaEmOutrosDocumentos" runat="server">
<asp:CheckBox runat="server" ID="Principal" AutoPostBack="True" OnCheckedChanged="ShowDiv"/>
</div>
Code Behind
public void ShowDiv(object sender, System.EventArgs e)
{
var div = ListaEmOutrosDocumentos as HtmlGenericControl;
var checkbox = sender as CheckBox;
if (checkbox.Checked == true)
{
div.Style.Clear();
div.Style.Add("display", "block");
}
else
{
div.Style.Clear();
div.Style.Add("display", "none");
}
}
What I am trying to achieve that if a user control already added to placeholder then it will be removed otherwise will be added to it and it will be done in a LinkButton's onclick.
The code:
public partial class SiteSettings : System.Web.UI.Page {
private UserSettings UserSettingsControl;
protected void Page_Load(object sender, EventArgs e) {
System.Diagnostics.Debug.WriteLine("Pageload");
UserSettingsControl = LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
}
protected void UserLink_Click(object sender, EventArgs e) {
if (SettingsPlaceholder.Controls.Contains(UserSettingsControl)) {
System.Diagnostics.Debug.WriteLine("Contains");
SettingsPlaceholder.Controls.Remove(UserSettingsControl);
} else {
System.Diagnostics.Debug.WriteLine("Does not Contains");
SettingsPlaceholder.Controls.Add(UserSettingsControl);
}
}
}
Now it is not working. And I am getting:
Pageload // on first time load
Pageload // on first time click
Does not Contains // on first time click
Pageload // on second time click
Does not Contains // on second time click
in the Output window.
How can I achieve this? I also tried to store it into ViewState, but since UserControl is not serializable so that didn't worked.
The aspx page is:
<telerik:RadAjaxManager ID="AjaxManager" runat="server">
<AjaxSettings>
<telerik:AjaxSetting AjaxControlID="UserLink">
<UpdatedControls>
<telerik:AjaxUpdatedControl ControlID="SettingsPanel" LoadingPanelID="LoadingPanel" UpdatePanelRenderMode="Block" />
<telerik:AjaxUpdatedControl ControlID="PlaceHolderPanel" />
</UpdatedControls>
</telerik:AjaxSetting>
</AjaxSettings>
<ClientEvents OnResponseEnd="respondEnd" />
</telerik:RadAjaxManager>
<asp:Panel ID="SettingsPanel" runat="server">
<telerik:RadSplitter ID="MainSplitter" runat="server" MinHeight="200" Width="100%"
OnClientLoaded="splitterLoaded" OnClientResized="splitterLoaded">
<telerik:RadPane ID="LeftPane" runat="server" MaxWidth="250" Width="150" MinWidth="150" CssClass="left-rounded-corner settings-splitter-left">
<asp:Panel runat="server">
<asp:LinkButton ID="UserLink" runat="server" onclick="UserLink_Click" Text="User Settings" />
</asp:Panel>
</telerik:RadPane>
<telerik:RadSplitBar ID="Splitbar" runat="server" CollapseMode="Forward" />
<telerik:RadPane ID="RightPane" runat="server" CssClass="right-rounded-corner settings-splitter-right">
<asp:Panel ID="PlaceHolderPanel" runat="server" Height="100%">
<asp:PlaceHolder runat="server" ID="SettingsPlaceholder" />
</asp:Panel>
</telerik:RadPane>
</telerik:RadSplitter>
</asp:Panel>
<telerik:RadAjaxLoadingPanel ID="LoadingPanel" runat="server" />
Edit:
Modified code:
public partial class SiteSettings : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
AddUserSettings();
}
}
public UserControl UserSettingsControl {
get {
if (ViewState["UserSettings"] == null) {
ViewState["UserSettings"] = LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
}
return (UserControl)ViewState["UserSettings"];
}
}
public UserControl SpaceSettingsControl {
get {
if (ViewState["SpaceSettings"] == null) {
ViewState["SpaceSettings"] = LoadControl("~/UserControls/SpaceSettings.ascx") as SpaceSettings;
}
return (UserControl)ViewState["SpaceSettings"];
}
}
protected void SettingsLink_OnCommand(object sender, CommandEventArgs commandEventArgs) {
switch (commandEventArgs.CommandName) {
case "User":
AddUserSettings();
break;
case "Space":
AddSpaceSettings();
break;
}
}
private void AddUserSettings() {
AddSettings(UserSettingsControl);
}
private void AddSpaceSettings() {
AddSettings(SpaceSettingsControl);
}
private void AddSettings(UserControl control) {
SettingsPlaceholder.Controls.Add(control);
}
}
Create a Property in your WebForm like below.
public UserSettings UserSettingsControl
{
get
{
if (Session["MyControl"] == null)
Session["MyControl"] =
LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
return (UserSettings)Session["MyControl"];
}
}
Now you can access the memory of UserSettingsControl. As it will persist across the Postback. In the original code, the UserSettingsControl was being reset to null across PostBack.
By end of the Page Life Cycle all the controls created at runtime
will be disposed. Finally, you cannot find the control created at
runtime after Postback. Only Recreation of the same control will be
required on each PostBack.
You could just not use a PlaceHolder and have the control there the whole time. Then the linkButton could toggle the visibility of the control.
The main problem is that the you are adding the control to the page linkButton click. Dynamically added controls work best when added in the Page_Init and Page_PreInit this allows them to maintain their ViewState. Also they have to be added to the placeholder on every postback. If in your example another control causes a postback after the SettingsControl is added to the placeholder, then the SettingsControl will disappear because it is not being added on every postback.
I have an ASP.Net 2.0 page that contains two UpdatePanels. The first panel contains a TreeView. The second panel contains a label and is triggered by a selection in the tree. When I select a node the label gets updated as expected and the TreeNode that I clicked on becomes highlighted and the previously selected node is no longer highlighted. However if a node is original highlighted(selected) in the code-behind the highlight is not removed when selecting another node.
The markup
<asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="false" UpdateMode="Conditional">
<ContentTemplate>
<asp:TreeView ID="TreeView1" runat="server" OnSelectedNodeChanged="TreeView1_SelectedNodeChanged">
<SelectedNodeStyle BackColor="Pink" />
</asp:TreeView>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdatePanel2" runat="server" ChildrenAsTriggers="True">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text=" - "></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="TreeView1" EventName="SelectedNodeChanged" />
</Triggers>
</asp:UpdatePanel>
The code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TreeView1.Nodes.Add(new TreeNode("Test 1", "Test One"));
TreeView1.Nodes.Add(new TreeNode("Test 2", "Test Two"));
TreeView1.Nodes.Add(new TreeNode("Test 3", "Test Three"));
TreeView1.Nodes.Add(new TreeNode("Test 4", "Test Four"));
TreeView1.Nodes[0].Selected = true;
}
}
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
Label1.Text = TreeView1.SelectedValue;
}
The at the start the first node is selected. Why is its highlight not removed when selecting another node?
Also, I asked a different question about the same setup that I haven't got an answer for. Any help would appreciated.
Edit I know that setting ChildrenAsTriggers="false" will work but I want to avoid rendering the tree again as it can be very large.
/// <summary>
/// Remove selection from TreeView
/// </summary>
/// <param name="tree"></param>
public static void ClearTreeView(TreeView tree)
{
if (tree.SelectedNode != null)
{
tree.SelectedNode.Selected = false;
}
}
You need to set the selection to false for all nodes.
I use something like this for one of my applications (with my treeview tvCategories):
public void RefreshSelection(string guid)
{
if (guid == string.Empty)
ClearNodes(tvCategories.Nodes);
else
SelectNode(guid, tvCategories.Nodes);
}
private void ClearNodes(TreeNodeCollection tnc)
{
foreach (TreeNode n in tnc)
{
n.Selected = false;
ClearNodes(n.ChildNodes);
}
}
private bool SelectNode(string guid, TreeNodeCollection tnc)
{
foreach (TreeNode n in tnc)
{
if (n.Value == guid)
{
n.Selected = true;
return true;
}
else
{
SelectNode(guid, n.ChildNodes);
}
}
return false;
}
This may be a bit of a hack but this will clear the selection on the client and avoid updating the panel.
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function BeginRequestHandler(sender, args)
{
var elem = args.get_postBackElement();
var selectedClassName = elem.id + '_1';
var arrAllElements = GetElementsByClassName(selectedClassName, elem);
var selectedNode = $get(elem.id + '_SelectedNode').value;
for(var i = 0; i < arrAllElements.length; i++)
{
if(arrAllElements[i].childNodes[0].id != selectedNode)
RemoveClassName(arrAllElements[i], selectedClassName );
}
}
);
It removes the selected style/class from all tree nodes unless its value is contained in the '_SelectedNode' hidden field.
GetElementsByClassName and RemoveClassName are in my own js library but are obvious enough.