I don't know the real answer behind the problem, and I've been defining my event handlers in the aspx. However, if you set a global to the Textbox, and then refer to the global in the handler you should be able to get it wired up.
Something like:
def
Page_Init(self):
global t
t = TextBox1
TextBox1.Text = "foo"
Button1.Click += Button1_Click
def
Button1_Click(sender,e):
global t
t.Text =
"bar"
Marked as answer by Dave Hayden on Dec 16, 2006 01:51 AM
And now for an asp.net IronPython newbie to braindump on what he thinks is happening, in hopes that somebody can let him know what the real answer is...
I think it has to do with the fact that this code behind file is not actually a class, but a python module with callable functions. For the Page_Init (), Page_Load() like methods, the new dynamic language compiler
is "injecting" page lifecycle like things into the method so that page lifecycle like things are available. However, in this case Button1_Click is not one of these special methods, and it is not defined in the aspx/ascx, so by default won't have access to
things like a real class method would (because it's not a class method, it's a callable python function in a module).
Normally with VB and C# your class is inherited from the generated page class and has access to all the members of that class, which includes controls, etc. However, with Python, no inheritance is taking place. A class, called ScriptPage, is instantiated
directly and injected into what would normally be page methods like Page_Init, Page_Load, etc. Therefore, my button event handler is not part of any class and has no clue about the label.
Rather than using a global variable, however, we do have access to the sender object ( of type button in this case ), which does expose a Page property that does give us access to the ScriptPage. We will set the text of the label that way:
cool! Getting the page context off of the button doesn't even feel like that much of a hack. Yeah, the global variable idea wasn't anything more then an attempt to prove what was going on, but not a real answer. Getting back to the Page off of the sender
sounds like a workable solution in general for ui control events.
You guys pretty much figured this one out. Ideally, this would just work directly (i.e. you could use Label1 directly in the handler), but the current implementation doesn't allow it. This is because in order to make this work, the IronPython logic needs
to insert itself on the stack to make the right context available. For Page_* methods, and when you do the hook up on the tag, the IronPython logic is in the picture and can do the right thing. But when you do the event hookup yourself (via +=), this goes
straight to ASP.NET, and IronPython doesn't get to insert the right context when the event is fired.
Hopefully we'll find a way to fix this. For now, your sender.Page workaround is fine. However, be aware that
it will not work correctly if you move this logic to a User Control (or master page), because sender.Page will evaluate to the Page, and not the User Control!
On the other hand, doing the hookup on the tag will always work correctly, so that would be my recommendation.
Hope this helps.
David
Marked as answer by davidebb on Dec 17, 2006 01:00 AM
Dave Hayden
Member
26 Points
19 Posts
Page_Init() and Programmatically Setting Click Handler
Dec 15, 2006 02:41 PM|LINK
I feel like a first-time programmer again using IronPython, which isn't all bad [:D]
The ASP.NET Personal Web Starter Kit doesn't show an example of something like this:
def Page_Init():
Button1.Click += Button1_Click
def Button1_Click(sender, args):
Label1.Text = "button1"
Everytime the Button1_Click event handler runs into Label1.Text, the application throws an exception saying Label1 does not exist.
However, if I define something like this:
<asp:Buttton ... OnClick="Button1_Click" ../> and removing Page_Init altogether, everything works fine.
I am sure it is a newbie mistake, but I am at a loss.
Thanks,
Dave
scotts
Member
32 Points
17 Posts
Re: Page_Init() and Programmatically Setting Click Handler
Dec 15, 2006 05:28 PM|LINK
Dave,
I don't know the real answer behind the problem, and I've been defining my event handlers in the aspx. However, if you set a global to the Textbox, and then refer to the global in the handler you should be able to get it wired up.
Something like:
def
Page_Init(self):global t
t = TextBox1
TextBox1.Text = "foo"
Button1.Click += Button1_Click
def
Button1_Click(sender,e): global tt.Text =
"bar"scotts
Member
32 Points
17 Posts
Re: Page_Init() and Programmatically Setting Click Handler
Dec 15, 2006 06:08 PM|LINK
And now for an asp.net IronPython newbie to braindump on what he thinks is happening, in hopes that somebody can let him know what the real answer is...
I think it has to do with the fact that this code behind file is not actually a class, but a python module with callable functions. For the Page_Init (), Page_Load() like methods, the new dynamic language compiler is "injecting" page lifecycle like things into the method so that page lifecycle like things are available. However, in this case Button1_Click is not one of these special methods, and it is not defined in the aspx/ascx, so by default won't have access to things like a real class method would (because it's not a class method, it's a callable python function in a module).
Dave Hayden
Member
26 Points
19 Posts
Re: Page_Init() and Programmatically Setting Click Handler
Dec 16, 2006 01:49 AM|LINK
I think you're right.
I spent the better part of a few hours learning a little about Python and reading this whitepaper:
http://www.asp.net/ironpython/WhitePaper.aspx?tabid=62
Normally with VB and C# your class is inherited from the generated page class and has access to all the members of that class, which includes controls, etc. However, with Python, no inheritance is taking place. A class, called ScriptPage, is instantiated directly and injected into what would normally be page methods like Page_Init, Page_Load, etc. Therefore, my button event handler is not part of any class and has no clue about the label.
Rather than using a global variable, however, we do have access to the sender object ( of type button in this case ), which does expose a Page property that does give us access to the ScriptPage. We will set the text of the label that way:
def Page_Init():
Button1.Click += Button1_Click
def Button1_Click(sender, args):
sender.Page.Label1.Text = "button1"
I appreciate the comments scotts as it got me in the right direction.
Pretty cool.
Regards,
Dave
scotts
Member
32 Points
17 Posts
Re: Page_Init() and Programmatically Setting Click Handler
Dec 16, 2006 02:17 AM|LINK
cool! Getting the page context off of the button doesn't even feel like that much of a hack. Yeah, the global variable idea wasn't anything more then an attempt to prove what was going on, but not a real answer. Getting back to the Page off of the sender sounds like a workable solution in general for ui control events.
davidebb
Contributor
7006 Points
1366 Posts
Microsoft
Re: Page_Init() and Programmatically Setting Click Handler
Dec 17, 2006 12:56 AM|LINK
You guys pretty much figured this one out. Ideally, this would just work directly (i.e. you could use Label1 directly in the handler), but the current implementation doesn't allow it. This is because in order to make this work, the IronPython logic needs to insert itself on the stack to make the right context available. For Page_* methods, and when you do the hook up on the tag, the IronPython logic is in the picture and can do the right thing. But when you do the event hookup yourself (via +=), this goes straight to ASP.NET, and IronPython doesn't get to insert the right context when the event is fired.
Hopefully we'll find a way to fix this. For now, your sender.Page workaround is fine. However, be aware that it will not work correctly if you move this logic to a User Control (or master page), because sender.Page will evaluate to the Page, and not the User Control!
On the other hand, doing the hookup on the tag will always work correctly, so that would be my recommendation.
Hope this helps.
David