1 / 41

Minneapolis Office Developer Interest Group (MODIG)

Minneapolis Office Developer Interest Group (MODIG). Neil Iversen Inetium. May 27, 2008 Web Part Development. http://justaddcode.com/. The Plan. Introduction  You are here Feature Presentation Web Part Development Next Topic Selection Random Stuff. User Group Goals.

Download Presentation

Minneapolis Office Developer Interest Group (MODIG)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Minneapolis Office Developer Interest Group (MODIG) Neil Iversen Inetium May 27, 2008 Web Part Development http://justaddcode.com/

  2. The Plan • Introduction  You are here • Feature Presentation • Web Part Development • Next Topic Selection • Random Stuff

  3. User Group Goals • Provide a community for SharePoint Developers • Share development knowledge • Exchange tips/tricks/other/free pizza • Add 2,000 attachments to an SPListItem…just for fun

  4. User Group Format • Presentations • 1-2 per meeting (targeting 1.25 Hours) • Hopefully Demo Heavy (Slides are for MBAs) • Highlights of Nifty Things • See next slide • QA/Discussion/Random Things

  5. Call for Cool Stuff • Created something cool? • Send Screenshots or Videos • We’ll try to feature some items here

  6. Sharepointmn.com/modig/ • Our current home • Meeting information • Usually has the right time • Previous presentations • Running on SharePoint • As required by SharePoint User Group Law

  7. Upcoming • Next Meeting • June 24 (Tuesday 5:30pm) • Topic: TBD – Hopefully later today • Location: UNKNOWN! • MNSPUG • June 11(9:00am – Noon) • Topic : TBD (sharepointmn.com) • Twin Cities SharePoint Camp • June 14 • www.twincitiessharepointcamp.com

  8. Developing Web Parts • Web Part Intro • Our First Web Part • Deploying Web Parts • Slightly More Interesting Web Parts

  9. Developing Web Parts • Used to be first exposure to SharePoint Development • Not as true in V3 • Most visual component in SharePoint Development

  10. Our First Decision • Derived From: • SharePoint WebPart v2 • SharePoint WebPart v3 • ASP.NET 2.0 WebPart

  11. Our First Decision • SharePoint WebPart v2 • Its Old, don’t use it • SharePoint WebPart v3 • Use for: • Cross Page Connections • Web Part Caching • Client Side Part to Part Communication (AJAX.net) • ASP.NET 2.0 WebPart • MS Recommended Approach • Even if they don’t follow their own recommendation • Some attributes are different between approaches • Personalization and ‘ToolParts/EditorParts’

  12. Demo – Our First Web Part

  13. The Lifecycle • OnInit • First thing to fire off • OnLoad • Runs after ViewState • CreateChildControls • Main control binding class • Events need to be defined here • PreRender • Last chance to modify before output happens

  14. What about that Render(HtmlWriter) Nonsense? • IMO - Skip it • Begin Mini-Rant • Lots of examples use it, they rarely need it • It causes ‘sync’ issues if you use both CreateChildControls and a write • Check your reason for using it, you can probably restructure your code to eliminate it • End

  15. Exception Management • try/catch in all code called by SharePoint • OnInit • CreateChildControls • PreRender • Any Events • button_Click • selectedIndexChanged

  16. Demo – Wiring Up an Event

  17. Making Things Personal • Tag your Public Property with: • WebBrowsable(true) • Does it show up in the ToolPane? • Personalizable(PersonalizationScope.User) • Saved with the User or Shared? • WebDisplayName("Favorite Widget") • The name in the ToolPane • WebDescription("Your Favorite Widget") • Tooltip in ToolPane • Category(“My Category") • Category Header in ToolPane • Ex • [Personalizable(PersonalizationScope.Shared)] public string MySavedProperty …

  18. Demo – Saving my Favorites

  19. Customizing the ToolPane • Why? • More Configuration Power • ToolParts and EditorParts • SharePoint vs ASP.net • Derive from EditorPart • ApplyChanges • Pushes the Changes back to the Web Part • SyncChanges • Pulls changes that may have happened on the Web Part back to the EditorPart • Web Part • Creates EditorPartCollection in CreateEditorPart()

  20. Demo – Custom EditorPart

  21. Playing Well With Others • Part to Part Communication • Providers • Provide the Data • Consumers • Consume the Data

  22. Implementing a Provider • Step 1: • //Step #1: Implement the Connection Interface (ICellProvider) public class CellProvider : WebPart, ICellProvider

  23. Implementing a Provider • Step 2: • //Step #2: Declare Connection Events public event CellProviderInitEventHandlerCellProviderInit; public event CellReadyEventHandlerCellReady;

  24. Implementing a Provider • Step 3: • //Step #3: EnsureInterfaces //Notification to the Web Part that is should ensure that all //its interfaces are registered using RegisterInterface. public override void EnsureInterfaces() { //Registers an interface for the Web Part RegisterInterface("MyCellProviderInterface_WPQ_", //InterfaceNameInterfaceTypes.ICellProvider, //InterfaceTypeWebPart.UnlimitedConnections, //MaxConnectionsConnectionRunAt.ServerAndClient, //RunAtOptions this, //InterfaceObject "CellProviderInterface_WPQ_", //InterfaceClientReference "Provide String from Textbox", //MenuLabel "Provides a Textbox string"); //Description }

  25. Implementing a Provider • Step 4: • //Step #4: CanRunAt - called by framework to determine where a part can run. public override ConnectionRunAtCanRunAt() { //This Web Part can run on both the client and the server return ConnectionRunAt.ServerAndClient; }

  26. Implementing a Provider • Step 5: • //Step #5: PartCommunicationConnect - Notification to the Web Part that it has been connected. public override void PartCommunicationConnect(string interfaceName, WebPartconnectedPart, string connectedInterfaceName, ConnectionRunAtrunAt) { //Check to see if this is a client-side part if (runAt == ConnectionRunAt.Client) { //This is a client-side part _runAtClient = true; return; } //Must be a server-side part so need to create the Web Part's controls EnsureChildControls(); //Check if this is my particular cell interface if (interfaceName == "MyCellProviderInterface_WPQ_") { //Keep a count of the connections _cellConnectedCount++; } }

  27. Implementing a Provider • Step 6: • //Step #6: PartCommunicationInit - Notification to the Web Part that it has been connected. public override void PartCommunicationInit() { //If the connection wasn't actually formed then don't want to send Init event if(_cellConnectedCount > 0) { //If there is a listener, send Init event if (CellProviderInit != null) { //Need to create the args for the CellProviderInit event CellProviderInitEventArgscellProviderInitArgs = new CellProviderInitEventArgs(); //Set the FieldNamecellProviderInitArgs.FieldName = _cellName; cellProviderInitArgs.FieldDisplayName = _cellDisplayName; //Fire the CellProviderInit event. CellProviderInit(this, cellProviderInitArgs); } } }

  28. Implementing a Provider • Step 7: • //Step #7: PartCommunicationMain - Called by the framework to allow part to fire any remaining events public override void PartCommunicationMain() { //If the connection wasn't actually formed then don't want to send Ready event if(_cellConnectedCount > 0) { //If there is a listener, send CellReady event if (CellReady != null) { //Need to create the args for the CellProviderInit event CellReadyEventArgscellReadyArgs = new CellReadyEventArgs(); //If user clicked button then send the value if (_cellClicked) { //Set the Cell to the value of the TextBox text //This is the value that will be sent to the Consumer cellReadyArgs.Cell = _cellInput.Text; } else { //The user didn't actually click the button //so just send an empty string to the Consumer cellReadyArgs.Cell = ""; } //Fire the CellReady event. //The Consumer will then receive the Cell value CellReady(this, cellReadyArgs); } } }

  29. Implementing a Provider • Step 8: • //Step #8: GetInitArgs is not needed in this case. GetInitEventArgs only needs to be //implemented for interfaces that can participate in a transformer which are //the following: ICellConsumer, IRowProvider, IFilterConsumer, IParametersOutProvider, //IParametersInConsumer

  30. Implementing a Provider • Step 9: • //Step #9: Implement CellConsumerInit event handler. public void CellConsumerInit(object sender, CellConsumerInitEventArgscellConsumerInitArgs) { //This is where the Provider part could see what type of "Cell" the Consumer //was expecting/requesting. //For this simple code example, this information is not used anywhere. }

  31. Implementing a Provider • Step 10: • //Step #10: RenderWebPart - defines Web Part UI and behavior protected override void RenderWebPart(HtmlTextWriter output) { //Need to ensure that all of the Web Part's controls are created EnsureChildControls(); //Render client connection code if the connection is client-side if (_runAtClient) { //Connected client-side output.Write(ReplaceTokens("<br><h5>Connected Client-Side</h5><br>\n" + "<input type=\"text\" id=\"CellInput_WPQ_\"/>\n" + "<button id=\"CellButton_WPQ_\" onclick=\"CellButtonOnClick_WPQ_()\">Fire CellReady</button>\n" + "<SCRIPT LANGUAGE=\"JavaScript\">\n" + "<!-- \n" + " varCellProviderInterface_WPQ_ = new myCellProviderInterface_WPQ_();\n" + " function myCellProviderInterface_WPQ_()\n" + " {\n" + " this.PartCommunicationInit = myInit;\n" + " this.PartCommunicationMain = myMain;\n" + " this.CellConsumerInit = myCellConsumerInit;\n" + " function myInit()\n" + " {\n" + " varcellProviderInitArgs = new Object();\n" + " cellProviderInitArgs.FieldName = \"CellName\";\n" + " WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellProviderInit\", cellProviderInitArgs);\n" + " }\n" + " function myMain()\n" + " {\n" + " varcellReadyArgs = new Object();\n" + " cellReadyArgs.Cell = \"\";\n" + " WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellReady\", cellReadyArgs);\n" + " }\n" + " function myCellConsumerInit(sender, cellConsumerInitArgs)\n" + " {\n" + " }\n" + " }\n" + " function CellButtonOnClick_WPQ_()\n" + " {\n" + " varcellReadyArgs = new Object();\n" + " cellReadyArgs.Cell = document.all(\"CellInput_WPQ_\").value;\n" + " WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellReady\", cellReadyArgs);\n" + " }\n" + "//-->\n" + "</SCRIPT>")); } else //Connected server-side { //If connected then display all cell child controls if (_cellConnectedCount > 0) { //Just render some informational text output.RenderBeginTag(HtmlTextWriterTag.Br); output.RenderEndTag(); output.RenderBeginTag(HtmlTextWriterTag.H5); output.Write("Connected Server-Side"); output.RenderEndTag(); output.RenderBeginTag(HtmlTextWriterTag.Br); output.RenderEndTag(); //Render the TextBox control _cellInput.RenderControl(output); //Render the Button _cellButton.RenderControl(output); } else { //There wasn't a cell connection formed, //so just output a message output.Write("NO CELL INTERFACE CONNECTION"); } } }

  32. Implementing a Provider • Step 11: • //Step #11.1 (Supporting Methods): CreateChildControls protected override void CreateChildControls() { //Create the Button _cellButton = new Button(); _cellButton.ID = "CellButton"; _cellButton.Text = "Fire CellReady"; Controls.Add(_cellButton); //Create the TextBox _cellInput = new TextBox(); _cellInput.ID = "CellInput"; Controls.Add(_cellInput); //Set the Cell information. //This information will be passed to the Consumer by //firing the CellProviderInit event. _cellName = "CellInput"; _cellDisplayName = "CellDisplayInput"; _cellClicked = false; // Initialize to false -- user hasn't clicked yet _cellButton.Click += new EventHandler(CellButtonClicked); // listen for Button's click event }

  33. Implementing a Provider • Phew! That’s a lot of code! • Or • [ConnectionProvider(“MyConnectionName“)] • And on the Consumer Side • [ConnectionConsumer(“MyConsumerName“)] • Thanks ASP.NET Team!

  34. Demo – Part to Part Communication

  35. Silverlight Web Parts • Its Easy • Add the Silverlight Host Control to the Page • And make 500 web.config changes

  36. Deployment • Deploy using Solutions • Assembly directive to deploy the DLL • Can add to SafeControls • DWP’s can be deployed as well

  37. Summary • Choose who you Derive from • Page Lifecycle • Storing Personalization Settings • Part to Part is much easier • Deployment is nicer than previous CABs

  38. Questions?

  39. References • Enable Silverlight 2 Beta 1 with a SharePoint Solution • http://blogs.inetium.com/blogs/pjirsa/archive/2008/05/08/enable-silverlight-2-beta-1-with-a-sharepoint-solution.aspx

  40. Next Meeting Planning • Possible Topics • More Web Part Development • Introduction to SharePoint Workflow • PowerShell and SharePoint for Developers • Using the MS AJAX Framework in SharePoint • Silverlight 2 and SharePoint • …

  41. Random Stuff Neil Iversen Inetium http://justaddcode.com Feedback Forms/Giveaway Mingle, Eat, Feedback See you next time!

More Related