CommandEventArgs null value in OnCommand event handler for a Custom WebControl implementing IButtonControl - asp.net

I am very sorry for the long title but I really didn't know how to be more self explaining than this.
The problem I have is this:
I designed and developed a WebControl which consists in a simple set of elements that, combined togheter in the simplest way, defines a custom button. This control is the one I would like to use in my web application instead of Button and LinkButton control (reasons mainly rely on graphic and visual functionalities).
In order to let the webcontrol behave like a button, it also implements the IButtonControl interface so that all elements needed by the framework in order to handle events and similar stuff are well provided.
Well, this button I called BoxButton works fine everytime it is used, instead for one thing.
Sorry for the long prelude, now we can go straight to the real problem:
In a page I have a ListView and in the listview I have the InsertItemTemplate enabled.
Well this insertitemtemplate works fine when the OnItemInsert is fired by pressing a button inside the template (a button, an ordinary button control).
Well, I sure wanted to place my BoxButton in place of the ordinary one. When I do this I have a problem.
The handler function is this:
protected void Insert_BoxButton_Command(object sender, CommandEventArgs e) {
if (e.CommandName == "Insert") {
// Do something
}
}
Typically, the e object is able to give information to the developer in order to locate all data to be inserted. These data are available when I use a normal button, but when using a BoxButton it is null!
Well, you could tell me that, when I defined my BoxButton implementing the IButtonControl interfaces, I had to manage with both the two events in the interface (dealing woth button pressure: Click and Command) and manage with the problem of providing CommandEventArgs. But how to do this?
Is there a solution to my problem? How can I manage eventargs? I sense that probably this is a very low programming issue... maybe there is much to do.
Thanks in advance for your help.
Andry

Related

How to validate controls inside editform template of ASPxGridView?

I have an ASPxGridView with edit form template and some bound controls inside. After update I want to validate, check the values in controls on server side. As far as I could find this is not possible. DevExpress recommends subscribing to the RowUpdating event, but this is plain wrong. Useless as is very much of their so called support.
The problem is, that if controls contains some invalid text and it raises an exception somewhere long before RowUpdating and it gets eaten by devexpress. All it comes back to client is some message like "Input string was not in a correct format".
I want to validate input controls on the server side.
And yes, I do row validating also, but this is useful only for validating business logic.
So, how to validate controls that are bound inside EditForm template on server side?
Could you please clarify? You want to validate the values after you update or actually before you write the values to the database or each control individually as it loses focus before you can initiate the update? If it is necessary to do server side validation then I would recommend doing it in the RowUpdating and RowInserting server side event handlers as was recommended by DevExpress. Why do you think this is wrong? You can validate each of the bound controls' values in the e.NewValues collection of grid's Updating and Inserting events. If any of the values do not pass validation you can cancel the update/insert action. Could you outline your desired workflow in a little more detail?
A previous poster said a hack was necessary, putting a container inside the edit form template, which is not true. You can use the edit form template itself via the .NamingContainer of any control in the edit form template. Put your validation routine in the server side _Validation event handler of the specific controls.
You can evaluate the template controls as a group:
EditFormValid = ASPxEdit
.AreEditorsValid(myGrid.FindEditFormTemplateControl("myControl")
.NamingContainer);
Or you can update a class variable during each control's validation routine
public class foo
{
bool EditFormValid = true;
.
.
.
void myControl_Validation(object sender, ValidationEventArgs e)
{
EditFormValid = EditFormValid && myControl.IsValid;
}
void myGrid_RowUpdating(object sender, ASPxDataUpdatingEventArgs e)
{
If(EditFormValid)
{
.
.
.
}
else e.Cancel = true;
}
}
I have found DevExpress extremely effective and flexible. However the flexibility can be a double edge sword as there are many ways to almost do everything you need most of the time but usually one way to do everything you need all of the time. A developer can easily build on top of what works in one instance but isn't necessarily right/best practice and get to a point where they have coded into a corner as they continue to build upon a project.
If you can provide more specifics, so can I.
As far as I know this is not possible to do. Devexpress controls leave a lot to wish for. There is no way to check if validation was successful. Clearly a big issue.
What you can do is to run validation again with ASPxEdit.AreEditorsValid(). But for this you would have to do a little hack (as always with devexpress).
Put a container inside your edit form, a simple div with runat="server" and ID would do. This is your container.
Than get his div with FindEditFormTemplate() and use it in ASPxEdit.AreDitorsValid().
This workaround has drawbacks:
clutters your aspx code with unnecessary elements
page execution on server side is slower
page rendering on browser side is slower
ValidateEditorsIncontainer() runs validation again so there is a big
performance hit
All of the above are trademarks of DevExpress controls. But look at it from the bright side. Their grid sometimes takes up to five unnnecesary server and database roundtrips just to start editing.

visual studio 2010 - preInit method

I'm using VS2010 and I'm going through some examples in my book and I'm trying to find the preInit method. I seem to recall in VS2008 for VB.Net all the Page LifeCycle methods were in the upper right hand side drop down for the "Page" element (upper left hand side).
Like I said I'm using VS2010 and in C#. In my upper left drop down all I see is _Default. The only PLC event I see is Page_Load. Do I have to manually type out the preInit method or is there a way to get it to auto populate like I've seen in VB using 2008?
I followed Kirill answer and it did everything he said it would. However, this is what it produced (Default.aspx is the name of the page I'm using):
private void _Default_PreInit(object sender, EventArgs e)
{
...
}
When I put a break point in there, it never got into that code block and the code was never run...
However, when I manually wrote it out using the following:
protected void Page_PreInit(object sender,EventsArgs)
{
...
}
The break point and the code in that block worked!
Any ideas?
Here is the answer.
If short:
In the solution explorer, right click the page and select "View
component designer" from the context
menu
open the properties panel/window (press F4)
now click the yellow arrow/flash icon and you will see a list of all
page events
double-click the event for which you want to add a handler
UPDATE
Yes you're right, it's not working as expected. Sorry for posting the answer without really checking if it works. I do not know how to fix it, but I've at least found the explanation.
Besides the method you've mentioned it also adds something like
private void InitializeComponent()
{
this.PreInit += new System.EventHandler(this._Default_PreInit);
}
It comes from the old designing/compilation model. After MS changed default designing/compilation model in ASP.NET 2.0., by default
AutoEventWireup is set to true, which instructs compiler to automatically
attach event handlers from the code behind/beside file using naming
convention (for the page events) e.g.
protected void Page_Load(...)
{
}
is automatically attached behind the scenes:
this.Load += new EventHandler(this.Page_Load)
So obviously the corresponding behavior of the Visual Studio 2010 was not changed according to these changes, and it still creates event handlers following the old naming convention and adding the delegate attaching method, which is no more necessary to have.
I found then answer to my question. I'm studying for the MCTS 70-515 exam and on Chapter 3 (pg.111) in the "Understanding the ASP.Net Life Cycle and Handling Events lesson I read the following paragraph:
Adding a C# Event Handler
"The code editor for C# also has an event handler drop-down list. However, it only contains access to events you have already provided handlers for. The C# environment provides a tool for wiring up control events, but it does not provide such a tool for the Page events. For these you have to code the event handler manually."
However, in a VB.Net web side, you get what I was originally describing with the 2 drop downs.

Can I get away with this or is it just too crude and unpractical?

I spent the whole of last night searching for a free AspNet web chat control that I could simply drag into my website. Well the search was in vain as I could not find a control that matched my needs i.e List of users, 1 to 1 chat, Ability to kick out users..
In the end I decided to create my own control from scractch. Although it works well on my machine Im concerned that It maybe a little crude and unpractical on a shared hosting enviroment.
Basically this is what I did :
Created an sql database that stores the chat messages.
Wrote the stored procedures and and included a statement that clears old messages
Then the 'crude' part :
Dragged an update panel and timer control on my page
Dragged a Repeater databound to the chat messages table inside the update panel
Dragged another update panel and inside it put a textbox and a button
Configured the timer control to tick every 5 seconds.
..and then I made it all work like this
In the timer tick event I 'refreshed' the messages display by invoking Databind() on my repeater i.e
protected void Timer1_Tick(object sender, EventArgs e)
{
MyRepeater.DataBind();
}
Then in my send button click event
protected void btnSend_Click(object sender, EventArgs e)
{
MyDataLayer.InsertMessage(Message, Sender, CurrTime);
}
Well It works well on my machine and Ive got the other functionalities(users list, kick out user..) to work by simply creating more tables.
But like I said it seems a little crude to me. so I need a proffesional opinion. Should I run with this or try another Approach ?
I'm not sure why you think it is crude - I would expect any other ASP.NET chat control to be developed in exactly the same fashion using client-side polling. As an alternative to using Update panels however, I would recommend writing the client-side AJAX functionality using JQuery (or some other Javascript framework) - the ASP.NET Update panel is really just a standard ASP.NET postback using a rendering trick so the screen doesn't have to be refreshed.
In regards to running with what you've got, if you've gone as far as you have already, I would continue on. It will be a great learning exercise on the requirements for your chat client even if you decide to replace it with something else down the track.

How do I add Page Events for ASP.NET in Visual Studio 2008

This is a bit of a Visual Studio question. I feel with all the helpful Intellisense there should be something to assist but I can't seem to find it.
I made a page with a codebehind in ASP.NET C# in VS2008 and it autogenerates a PageLoad event method, of course. Well, what if I want to add methods for more events besides PageLoad? I would think there would be some list on the Foo.aspx page of possible method event handlers to add. Aren't there more maybe like PageInit, PageDispose, (or equiv) etc...? Where can I find these?
EDIT - I can of course look up the method names in the api. I'm looking for a handy shortcut to add these in Visual Studio. If it generates one, can't it make others?
In the solution explorer, right click the page and select "View component designer" from the context menu
open the properties panel/window (press F4)
now click the yellow arrow/flash icon and you will see a list of all page events
double-click the event for which you want to add a handler
I'm pretty sure there was another way (starting from the designer view), but I can't reproduce it.
I usually do not use the page event handlers, instead I override the corresponding methods (e.g. OnLoad instead of Page_Load). To implement one of these overrides, you can simply type "override" in the code-behind and press space to get a list of methods that you can override.
With the invaluable ReSharper installed (might work without) I can just type:
override
and when I hit space IntelliSence pops up with a list of all the events that I can override such as OnInit, OnPreRender, etc.
as a shortcut to see what's available, you could always just type "Page." and then take a look a the list in intellisense. You could then pick one, hit +=Tab Tab to have it generate the stub for you. once the stub is created, you'd have to delete the "Page.event+=" line wherever you created it. Kind of a hokey workaround, but can work pretty quick once you get the hang of it.
In the source code window, from the object list combo box, select the desired control (page). Then from the event list combo box that is to the right of the previous object list combo box select the desired event. Visual studio will create the event handler for you.
If one wants to not use the way as described by M4N but through code:
In the PageName.aspx.cs;
private void InitializeComponent()
{
// this.LifeCycle += .. // Use intellisense to see alternatives easily
this.PreRender += new System.EventHandler(this.EventFunctionName);
}
then in the same file add:
private void EventFunctionName(object sender, EventArgs e)
{
// Code..
}
UPDATE (from comment by Sahuagin):
This won't generate an event handler with the appropriate name. The event handler must be named, for example, Page_Load. This will name it after your class rather than after Page, and so it won't actually be hooked up to your page
TreeScheme.Nodes[0].ChildNodes[0].Checked=true;
treeviewid.node[0].childnodes[0].checked=true;
This will set the child node checked true in page load event of page
happy coding

Child Control Initialization in Custom Composite in ASP.NET

Part of the series of controls I am working on obviously involves me lumping some of them together in to composites. I am rapidly starting to learn that this takes consideration (this is all new to me!) :)
I basically have a StyledWindow control, which is essentially a glorified Panel with ability to do other bits (like add borders etc).
Here is the code that instantiates the child controls within it. Up till this point it seems to have been working correctly with mundane static controls:
protected override void CreateChildControls()
{
_panel = new Panel();
if (_editable != null)
_editable.InstantiateIn(_panel);
_regions = new List<IAttributeAccessor>();
_regions.Add(_panel);
}
The problems came today when I tried nesting a more complex control within it. This control uses a reference to the page since it injects JavaScript in to make it a bit more snappy and responsive (the RegisterClientScriptBlock is the only reason I need the page ref).
Now, this was causing "object null" errors, but I localized this down to the render method, which was of course trying to call the method against the [null] Page object.
What's confusing me is that the control works fine as a standalone, but when placed in the StyledWindow it all goes horribly wrong!
So, it looks like I am missing something in either my StyledWindow or ChildControl. Any ideas?
Update
As Brad Wilson quite rightly pointed out, you do not see the controls being added to the Controls collection. This is what the _panel is for, this was there to handle that for me, basically then override Controls (I got this from a guide somewhere):
Panel _panel; // Sub-Control to store the "Content".
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return _panel.Controls;
}
}
I hope that helps clarify things. Apologies.
Update Following Longhorn213's Answer
Right, I have been doing some playing with the control, placing one within the composite, and one outside. I then got the status of Page at event major event in the control Lifecycle and rendered it to the page.
The standalone is working fine and the page is inited as expected. However, the one nested in the Composite is different. It's OnLoad event is not being fired at all! So I am guessing Brad is probably right in that I am not setting up the control hierarchy correctly, can anyone offer some advice as to what I am missing? Is the Panel method not enough? (well, it obviously isn't is it?!) :D
Thanks for your help guys, appreciated :)
I don't see you adding your controls to the Controls collection anywhere, which would explain why they can't access the Page (since they've never been officially placed on the page).
I have always put the JavaScript calls on the OnLoad Function. Such as below.
protected override void OnLoad(EventArgs e)
{
// Do something to get the script
string script = GetScript();
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "SomeJavaScriptName", script);
// Could also use this function to determine if the script has been register. i.e. more than 1 of the controls exists
this.Page.ClientScript.IsClientScriptBlockRegistered("SomeJavaScriptName");
base.OnLoad(e);
}
If you still want to do the render, then you can just write the script in the response. Which is what the RegisterScriptBlock does, it just puts the script inline on the page.
Solved!
Right, I was determined to get this cracked today! Here were my thoughts:
I thought the use of Panel was a bit of a hack, so I should remove it and find out how it is really done.
I didn't want to have to do something like MyCtl.Controls[0].Controls to access the controls added to the composite.
I wanted the damn thing to work!
So, I got searching and hit MSDN, this artcle was REALLY helpful (i.e. like almost copy 'n' paste, and explained well - something MSDN is traditionally bad at). Nice!
So, I ripped out the use of Panel and pretty much followed the artcle and took it as gospel, making notes as I went.
Here's what I have now:
I learned I was using the wrong term. I should have been calling it a Templated Control. While templated controls are technically composites, there is a distinct difference. Templated controls can define the interface for items that are added to them.
Templated controls are very powerful and actually pretty quick and easy to set up once you get your head round them!
I will play some more with the designer support to ensure I fully understand it all, then get a blog post up :)
A "Template" control is used to specify the interface for templated data.
For example, here is the ASPX markup for a templated control:
<cc1:TemplatedControl ID="MyCtl" runat="server">
<Template>
<!-- Templated Content Goes Here -->
</Template>
</cc1:TemplatedControl>
Heres the Code I Have Now
public class DummyWebControl : WebControl
{
// Acts as the surrogate for the templated controls.
// This is essentially the "interface" for the templated data.
}
In TemplateControl.cs...
ITemplate _template;
// Surrogate to hold the controls instantiated from
// within the template.
DummyWebControl _owner;
protected override void CreateChildControls()
{
// Note we are calling base.Controls here
// (you will see why in a min).
base.Controls.Clear();
_owner = new DummyWebControl();
// Load the Template Content
ITemplate template = _template;
if (template == null)
template = new StyledWindowDefaultTemplate();
template.InstantiateIn(_owner);
base.Controls.Add(_owner);
ChildControlsCreated = true;
}
Then, to provide easy access to the Controls of the [Surrogate] Object:
(this is why we needed to clear/add to the base.Controls)
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return _owner.Controls;
}
}
And that is pretty much it, easy when you know how! :)
Next: Design Time Region Support!
Right, I got playing and I figured that there was something wrong with my control instantiation, since Longhorn was right, I should be able to create script references at OnLoad (and I couldn't), and Brad was right in that I need to ensure my Controls hierarchy was maintained by adding to the Controls collection of the composite.
So, I had two things here:
I had overriden the Controls property accessor for the composite to return this Panel's Controls collection since I dont want to have to go ctl.Controls[0].Controls[0] to get to the actual control I want. I have removed this, but I need to get this sorted.
I had not added the Panel to the Controls collection, I have now done this.
So, it now works, however, how do I get the Controls property for the composite to return the items in the Panel, rather than the Panel itself?

Resources