Is this useful or is there an obvious other way?
The context is solving the problem of bubbling events in an asp.net site built with user controls and nested user controls. I found myself writing a ton of events.
So instead of events, i'm using a technique to allow any client to watch an arbitrary session value.
A shared context class for Page and UserControl. Updates to session values go through here as well as registrations for session value changes.
public class WebSiteContext
{
private WebSitePage _webSitePage;
public WebSiteContext(WebSitePage webSitePage)
{
_webSitePage = webSitePage;
}
internal void SetSessionValue<T>(string key, T value)
{
object current = _webSitePage.Session[key];
if (current != null && current.Equals(value)) return;
_webSitePage.Session[key] = value;
if (_dic.ContainsKey(key)) _dic[key](value);
}
internal Dictionary<string, Action<object>> _dic = new Dictionary<string, Action<object>>();
internal void WhenSessionValueChanges(string key, Action<object> action)
{
_dic.Add(key, action);
}
}
Base page constructor creates context instance.
public class WebSitePage : System.Web.UI.Page
{
public WebSitePage()
{
this.WebSiteContext = new WebSiteContext(this);
}
public WebSiteContext WebSiteContext { get; set; }
}
Base user control property to get context from parent page.
public class WebSiteUserControl : System.Web.UI.UserControl
{
public WebSiteContext WebContext {
get {
return (this.Page as WebSitePage).WebSiteContext;
}
}
}
A user control makes a change to a session value.
public partial class AdvertiserSelector : WebSiteUserControl
{
protected void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
this.WebContext.SetSessionValue(
SessionKeys.current_advertiser_id,
(sender as ComboBox).SelectedValue);
}
}
Now in my web page code behind, instead of subscribing to an event, an action is registered for a session value change.
namespace WebApplication1.Screens.CampaignSpend
{
public partial class Default : WebSitePage
{
protected void Page_Load(object sender, EventArgs e)
{
this.WebSiteContext.WhenSessionValueChanges(SessionKeys.current_advertiser_id, c => GridView1.DataBind());
}
}
}