I have embedded a WebGrid into a SharePoint web part and it works OK - I create the grid programatically and add it using CreateChildControls method.
I have one issue which is after I add my WegGrid-containing web part to the MOSS page. I do this in MOSS via Site Actions - Edit Page and edit the web part page, click a web part zone and pick my web part to add it. It goes onto the page fine, but I can't close the web part using the X in the top right corner. I can add other built-in web parts to the page and close them OK, e.g. content query web part, content editor web part etc. But when I try to close my own web part in MOSS the browser doesn't post back and just does nothing. The same thing happens if I click the Edit dropdown and select Close or Delete - again the web part is not removed from the page.
I know this isn't a MOSS forum but I wonder if anyone else has had this problem? Seems like it might be to do with Javascript on the page?
The browser is IE7. Firefox doesn't have the same issue but you need to use IE really for MOSS work.
OK Thanks. I tried making my web part class implement INamingContainer but it still behaves the same, jams up the postback when you try to close it on the page.
I found this blog entry by Todd Snyder of Infragistics where he managed to do something similar to what I'm trying to do:
http://blogs.infragistics.com/blogs/tsnyder/archive/2008/07/29/getting-sharepoint-and-ms-ajax-to-work-together-is-lots-of-fun.aspx
He has embedded the WebGrid in an UpdatePanel, which I don't need to do. He doesn't set the ID property of the grid I notice - like I say when I do set the ID after creating the grid object, it seems to mess things up when the page refreshes.
Oh, I see - so you are ahead of me with this one. So yes - in this case (with GUIDs) the ID will probably not match the ID expected on postback/AJAX callback. But then again, I am not sure that even with IDs provided from the framework we will always have exact match then - since the IDs are provided by the Control Tree and it might be different at the time you are adding the controls back - especially if you have added/deleted additional controls from the parent containers.
I will probably need to set this up and reproduce it before advising further. Just on top of my head a couple of suggestions - the ID can be equal to the container WebPart.ID + something unqiue, like "WebGrid" as a suffix. Also, you may mark the WebPart with INamingContainer inteface and see if it works better (ctrl000 as autogenerated ID seems weirds, since for child controls the ID in INamingContainers needs to be somethng like parentID_ctrl00 if ID of the child is not set explicitly).
But I must admit I am shooting in the dark here - hopefully someone more experienced will provide additional clues.
Thanks Rumen for that.
Can you explain is it actually necessary to keep setting the ID of the grid to a new GUID?, or in fact why do you need to set the ID at all? I thought .NET takes care of all this and you should not need to set the ID to be unique?
I found actually in a larger app that I am writing that if you do reset the ID of the grid every time in CreateChildControls, it messes up the AJAX paging - presumably it loses track of the grid if the ID keeps changing. I tried setting a breakpoint on the web part and attached Visual Studio remotely to the W3WP process to debug it. Then I tried paging back and forth using the AJAX paging. I found that if you don't set the ID explicitly, it repeatedly references the Grid property via calls to get(). Because the grid is created without an explicit ID, it gets allocated an ID for example "ctl100". Presumably that ID is the way that .NET keeps track of the state of the grid - it's probably not a good idea to change it every time?
If so that it comes back to the original question as to why, if you don't set the ID on the grid, it messes up the postback on the page if you try to close or delete the web part. I don't have this problem with the normal .NET GridView control so I guess I just have to use that instead. But of course I'd like to have the extra functionality of the Infragistics grid - if anyone else has got this issue resolved it would be good to know.
Anyway here's another tip that I picked up on this project - if anyone else tries to embed a webgrid into a web part then you must override the OnInit() method as follows:
protected override void OnInit(EventArgs e) { base.OnInit(e); this.EnsureChildControls(); }
If you don't do that then the InitializeDataSource method is never called. You need to set the DataSource in that InitializeDataSource method. You don't need to call DataBind() directly - it will bind when it displays.
I think this could be a combined INamingContainer / javascript variable naming issue. I have just tried your code (thanks for sharing) and it appears that using numbers as IDs is not valid in javascript - the variable name must start with letter, "_", etc, so if you are not appending this to a control that implements INamingContainer (and has a valid explicitly set ID), you will get invalid javascript ID handles and errors.
Guids are also problematic sometimes, because their parts are delimited with "-" which is again not valid (I am not completely sure why you did not get error there). I believe the safest way to go is something like this:
_grid = new UltraWebGrid(); _grid.ID = "WebGrid" + System.Guid.NewGuid().ToString().Replace("-", "_");
This will guarantee uniquess, plus the handle of the javascript client ID will be correct even if you are not adding your WebPart to a control implementing INamingContainer. I have just tried the following with good results
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //Guid u = System.Guid.NewGuid(); PlaceHolder1.Controls.Add(new UltraGridDemoWP2()); PlaceHolder1.Controls.Add(new UltraGridDemoWP2()); PlaceHolder1.Controls.Add(new UltraGridDemoWP2()); } public class UltraGridDemoWP2 : System.Web.UI.WebControls.WebParts.WebPart { private UltraWebGrid _grid; public UltraWebGrid Grid { get { EnsureChildControls(); return _grid; } } protected override void CreateChildControls() { base.CreateChildControls(); _grid = new UltraWebGrid(); _grid.ID = "WebGrid" + System.Guid.NewGuid().ToString().Replace("-", "_"); this.Controls.Add(_grid); Bind(); // Comment this out and it doesn't jam up the postback } private void Bind() { Grid.DataSource = getdata(); Grid.DataBind(); } private DataTable getdata() { DataTable t = new DataTable(); t.Columns.Add(new DataColumn("Col1")); t.Columns.Add(new DataColumn("Col2")); for (int i = 0; i < 10; i++) { DataRow r = t.NewRow(); r["Col1"] = "col1-" + i.ToString(); r["Col2"] = "col2-" + i.ToString(); t.Rows.Add(r); } return t; } }
OK thanks - I'm using NetAdvantage 2008 CLR. 2.0