title: ASP.NET issues databinding to simple object
body: <p>I am trying to databind my form inputs to various properties in a session state object.  I'm really new to ASP.NET, but when I've done this in WPF applications, I just needed to implement the INotifyPropertyChanged interface and the binding/updating "just worked".  Trying to do it here, the values never get loaded into the control unless I manually call DataBind(), and if I change the values in the control, they never get written back to the object.  My goal would be to manage the databinding entirely in the ASPX, without having to call DataBind() in the codebehind.  Can somebody help me figure out what's wrong here?</p>
  
  <p>ASPX:</p>
  
  <pre><code>&lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FormDataBindTest.Default" %&gt;
  
  &lt;!DOCTYPE html&gt;
  
  &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
  &lt;head runat="server"&gt;
      &lt;title&gt;&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;form id="form1" runat="server"&gt;
          &lt;asp:TextBox ID="value" Text="&lt;%# obj.Value %&gt;" runat="server" /&gt;
          &lt;asp:HiddenField ID="valuePlusOne" Value="&lt;%# obj.ValuePlusOne.ToString() %&gt;" runat="server" /&gt;
          &lt;asp:Button ID="submit" Text="Submit" runat="server" /&gt;
      &lt;div&gt;
          &lt;%= PrintForm() %&gt;
      &lt;/div&gt;
      &lt;/form&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Codebehind:</p>
  
  <pre><code>using System;
  using System.ComponentModel;
  using System.Text;
  
  namespace FormDataBindTest
  {
      public class MyObject :INotifyPropertyChanged
      {
          int _value;
          public int Value { get { return _value; } set { _value = value; Notify("Value"); Notify("ValuePlusOne"); } }
          public int ValuePlusOne { get { return Value + 1; } }
  
          public event PropertyChangedEventHandler PropertyChanged;
  
          public void Notify(string property)
          {
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
          }
      }
      public partial class Default : System.Web.UI.Page
      {
          static protected MyObject obj;
          protected void Page_Load(object sender, EventArgs e)
          {
              if (obj == null)
                  obj = new MyObject();
  
              if (!IsPostBack)
              {
                  obj.Value = 100;
              }
  
              DataBind();
          }
  
          protected string PrintForm()
          {
              StringBuilder sb = new StringBuilder();
              if (IsPostBack)
              {
                  sb.AppendLine("&lt;hr&gt;");
                  sb.AppendLine("&lt;h1&gt;Form Contents&lt;/h1&gt;");
                  sb.AppendLine("&lt;br&gt;");
  
                  foreach (string key in Request.Form.AllKeys)
                  {
                      sb.AppendLine(key + "= " + Request.Form[key]);
                      sb.AppendLine("&lt;br&gt;");
                  }
              }
  
              return sb.ToString();
          }
      }
  }
  </code></pre>