I'm trying to use data binding to disable a button in ASP.NET, but the button remains enabled. What am I doing wrong? Here is my example program which demonstrates the problem.
Default.aspx:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<div>
<asp:Button runat="server" Text="Button 1" Enabled="<%# false %>" /><br />
<asp:Button runat="server" Text="Button 2" Enabled="<%# PropertyReturnsFalse %>" /><br />
<asp:Button runat="server" Text="Button 3" Enabled="<%# StaticPropertyReturnsFalse %>" /><br />
<asp:Button runat="server" Text="Button 4" Enabled="true" /><br />
<asp:Button runat="server" Text="Button 5" Enabled="false" /><br />
</div>
</asp:Content>
Default.aspx.cs:
using System;
using System.Web.UI;
namespace WebApplication1
{
public partial class _Default : Page
{
public bool PropertyReturnsFalse
{
get { return false; }
}
public static bool StaticPropertyReturnsFalse
{
get { return false; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
I expect button 4 to be enabled and buttons 1, 2, 3, and 5 to be disabled. The actual result at run time is that buttons 1, 2, 3, and 4 are enabled, and only button 5 is disabled.
I know ASP.NET is matching the property names in the ASPX file to the code-behind, because if I change the ASPX file to a mismatch, I get an error. I get no error when the names match.
I set breakpoints on the property implementations. Neither breakpoint gets hit at run time.
CodePudding user response:
Well, if you going to use a data bound expression for control? Then like a listbox, dropdown, gridview or anything else? Those expressions ONLY fire if you do a data bind on that control.
eg:
GridView1.DataBind();
So, in your case, if you want those expressions to "run" or be evaluated, then you need to execute a databind for that given control.
Hence this:
<div>
<asp:Button ID="btn1" runat="server" Text="Button 1" Enabled="<%# false %>" /><br />
<asp:Button ID="btn2" runat="server" Text="Button 2" Enabled="<%# PropertyReturnsFalse %>" /><br />
<asp:Button ID="btn3" runat="server" Text="Button 3" Enabled="<%# StaticPropertyReturnsFalse %>" />
<br />
</div>
<asp:Button ID="Button1" runat="server"
OnClick="Button1_Click" Text="Run binding code" Width="155px" />
And code behind then becomes this:
protected void Button1_Click(object sender, EventArgs e)
{
btn1.DataBind();
btn2.DataBind();
btn3.DataBind();
}
I mean, you probably don't want to use a data binding event for a button, since we not binding data to that button (at least in most cases we are not!).
So, you could dump use of data binding expression.
At this point one would be VERY tempted to change the "#" to a "=" which means a server side expression, but server controls with a runat=server don't allow such expressions, since they are already server side (they allow binding ones "#", but not server side ones "=".
So, this means you move that code to page load, like this:
protected void Page_Load(object sender, EventArgs e)
{
btn1.Enabled = false;
btn2.Enabled = PropertyReturnsFalse;
btn3.Enabled = StaticPropertyReturnsFalse;
}
So, sever side controls don't accept markup expressions like '<%= %>', since they are already server side code - and you can do what amounts to the same thing by placing such code in on-load. Those expressions would run each time on page load anyway - so, no big deal to place in page load.
but, databind() expressions can be used - but then you have to execute a databind for that given control for the binding expression to trigger.