ToolPart in SmartPart 1.1

Sep 17, 2007 at 10:39 AM
Hallo,

Can someone post any kind of ToolPart implementation example of the SmartPart. SmartPart is a great thing for any kind of Webpart, but I really need custom propertys that will be adjustable in the ToolPart not just Hidden Custom Propertys.

PLEASE ANY KIND OF HELP/HINT IS VERY HELPFULL.

Dejan.
Sep 27, 2007 at 6:59 PM
I just got done doing this and it is not as bad as you might think. To start you need to "Import" or "Using" your smartpart dll, then your .ascx file needs to look like this (All VB code in my example) look like this

Imports Microsoft.SharePoint
Imports SmartPart
Imports System.Data
Imports ReportToolpt <--This is my tool part assemly
Imports System.Web.UI.WebControls

Partial Class ReportControl
Inherits System.Web.UI.UserControl
Implements SmartPart.IAdvancedUserControl

After you implement the SmartPart.IAdvancedUserControl you will need to do two things
1. Create a function that gets the custom toolpart that you will create. This will be called automatically when you select "Modify Shared Webpart"

Public Function GetCustomToolParts() As Microsoft.SharePoint.WebPartPages.ToolPart() Implements SmartPart.IAdvancedUserControl.GetCustomToolParts
Dim toolParts(1) As WebPartPages.ToolPart
MyTp is just my custom toolpart
Dim MyTp As New ReportToolPartClass
toolParts(0) = MyTp
Return toolParts
End Function

2. Set the context of your webpart
Public Sub SetContext(ByVal webpart As SmartPart.SmartPart) Implements SmartPart.IAdvancedUserControl.SetContext
'Set the context of your smartpart
mypart = webpart
End Sub

This will give you all of your necessary parts for your smartpart to call the toolpart. In order for your tool part to be able to modify properties in your smartpart make any properties that you have look like this

_<ComponentModel.Browsable(False), ComponentModel.DefaultValue(0), WebPartPages.WebPartStorage(WebPartPages.Storage.Shared)> _
Property ReportID() As Integer
Get
Return webReportID
End Get
Set(ByVal Value As Integer)
webReportID = Value
End Set
End Property

Now here is the funny thing once the tool part has changed your properties and closed I have not gotten it to actually "Get" the local variable such as webReportID in my example to do this I actually have to mannually get this value in the Page Load Event by going
webReportID = mypart.GetCustomProperty("ReportID")
This then sets the customproperty to what was entered into the toolpart. If anyone can steer me in the right direction as far as this goes I would greatly appreciate it, however for now this seems to work as unelegant as it may be.

Now for the Tool Part------------------
The tool part needs to inherit "Microsoft.SharePoint.WebPartPages.ToolPart"

Imports System.Web.ui
Imports System.Web.UI.WebControls
Imports Microsoft.SharePoint
Imports Evolve.Data.Framework.Reporting

Public Class ReportToolPartClass : Inherits Microsoft.SharePoint.WebPartPages.ToolPart

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
MyPart = Me.ParentToolPane.SelectedWebPart
End Sub

Protected Overrides Sub CreateChildControls()
CreateSelectReportControls()
End Sub

This overridden procedure is called when the "Apply" button is hit on the report tool part
Public Overrides Sub ApplyChanges()
EnsureChildControls()
GetControlValues()
MyPart.RefreshPropertyValues()
MyPart.SaveWebPartProperties = True
End Sub

This is called when the "OK" button is hit. I am not sure why but I needed to call the "ApplyChanges" method twice in order to have the properties that were entered into the tool part acttually take effect. All this really does is reload the page twice and that seems to make the properties take hold. I am sure that this has somthing to do with the way that I am getting the property values in the webpart itself. Again if anyone has any better way to do this I am all ears.
Public Overrides Sub SyncChanges()
ApplyChanges()
ApplyChanges()
MyBase.SyncChanges()
End Sub

I found it necessary to actually render the controls that I put in the tool part in order to space them out enough, otherwise the all just pilled next to each other and it was not a very attractive look. However if you just had one control all you need to do is "Me.Controls.Add(your control)." So when Rendering the controls on the toolpart I had to first populate them with the current values of the tool part.
Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
EnsureChildControls()
PopulateControlValues()
End Sub

This is just calling the procedure to render my dropdown
_Protected Overrides Sub RenderToolPart(ByVal output As System.Web.UI.HtmlTextWriter)
_EnsureChildControls()
_RenderSelectReportDropDownListControls(output)
_End Sub

Just creates my dropdown or any control that you would like to add
_ Private Sub CreateSelectReportControls()_
ddlSelectReport = New DropDownList
ddlSelectReport.ID = "ddlReport"
li = New ListItem("(none)", 0)
ddlSelectReport.Items.Add(li)
Controls.Add(ddlSelectReport)
End Sub

This is the procedure that is called in the overridden prerender. This just gets the current values that my smartpart has in it and applys it to the controls that I added.
Private Sub GetControlValues()
newReportID = Convert.ToInt32(ddlSelectReport.SelectedValue)
MyPart.SetCustomProperty("ReportID", newReportID)
End Sub

This populates the values that the user enters into the tool part into your currently selected web part. Again I had to use the GetCustomProperty method of the smartpart.
Pivate Sub PopulateControlValues()
ddlSelectReportReport.SelectedValue = ddlSelectReport.Items.FindByValue(MyPart.GetCustomProperty("ReportID")).Value
End Sub

This finally renders the dropdown that I created above. As you can see I used a HtmlTextWriter to put a line break into the toolpart to space it out a little
Private Sub RenderSelectReportDropDownListControls(ByRef output As System.Web.UI.HtmlTextWriter)
output.Write("</br>")
ddlSelectReport.RenderControl(output)
End Sub
and that is it if you have any questions feel free to ask
Oct 30, 2007 at 5:41 PM
Edited Oct 30, 2007 at 5:42 PM
Thanks this was helpful. Still having an issue with blank values showing up in my toolpart whenever I "modify web part", but this got me most of the way.

It seems you can avoid setting in page load if you call GetCustomProperty in the webpart's property:

Browsable(false), DefaultValue(0), WebPartStorage(Storage.Shared)
public string ColorCategoryListName
{
get
{
if (this.curSmartPart.GetCustomProperty("ColorCategoryListName") != null)
return this.curSmartPart.GetCustomProperty("ColorCategoryListName").ToString();
else
return
String.Empty;
}
set
{
this.curSmartPart.SetCustomProperty("ColorCategoryListName", value);
}
}

Also, I did not have to do the ApplyChanges multiple times with the toolpart code below.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
namespace NGP.SharePoint.Controls.Common.ToolParts
{
ToolboxData("<{0}:PoliticalCalendarToolPart runat=server></{0}:PoliticalCalendarToolPart>")
public class PoliticalCalendarToolPart : ToolPart
{
// declaring a sample varialble
//private string inputname;

// an event handler for the Init event
private void PoliticalCalendarToolPart_Init(object sender,
System.EventArgs e)
{
//inputname = this.UniqueID + "message";
}

/// <summary>
/// Constructor for the class. A great place to set Set
/// default values for additional base class properties
/// here.
/// <summary>

public PoliticalCalendarToolPart()
{
// Set default properties
this.Title = "Custom Text";
this.Init += new EventHandler(PoliticalCalendarToolPart_Init);
}
SmartPart.SmartPart MyPart;
protected override void OnLoad(EventArgs e)
{
MyPart = (SmartPart.SmartPart)this.ParentToolPane.SelectedWebPart;
}
Table tbl = new Table();
TextBox txtColorCategory = new TextBox();
TextBox txtSiteUrl = new TextBox();

protected void AddLabelAndTextBoxToTable(string LabelText, TextBox txt)
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
tbl.Rows.Add(tr);
tr.Cells.Add(tc);
Label l = new Label();
l.Text = LabelText;
tc.Controls.Add(l);

tr = new TableRow();
tc = new TableCell();
tbl.Rows.Add(tr);
tr.Cells.Add(tc);
//txtColorCategory.ID = "txt" + TextBoxText;
tc.Controls.Add(txt);

}

protected override void CreateChildControls()
{
this.AddLabelAndTextBoxToTable("Color Category List:", txtColorCategory);
this.AddLabelAndTextBoxToTable("Site Url:", txtSiteUrl);

//get is not working on post back in any event
if (!this.Page.IsPostBack)
{
try
{
txtColorCategory.Text = MyPart.GetCustomProperty("ColorCategoryListName").ToString();
}
catch (Exception ex)
{
txtColorCategory.Text = "Could not get color category.";
}
try
{
txtSiteUrl.Text = MyPart.GetCustomProperty("SiteUrl").ToString();
}
catch (Exception ex)
{
txtSiteUrl.Text = "Could not get color category.";
}
}
this.Controls.Add(tbl);
}
/// <summary>
/// Called by the tool pane to apply property changes to
/// the selected Web Part.
/// </summary>
public override void ApplyChanges()
{
SmartPart.SmartPart wp1 = (SmartPart.SmartPart)this.ParentToolPane.SelectedWebPart;
wp1.SetCustomProperty("ColorCategoryListName", txtColorCategory.Text);
wp1.SetCustomProperty("SiteUrl", txtSiteUrl.Text);

MyPart.RefreshPropertyValues();
MyPart.SaveWebPartProperties = true;
// Send the custom text to the Web Part.
//wp1.c = Page.Request.Forminputname;
}

/// <summary>
/// If the ApplyChanges method succeeds, this method is
/// called by the tool pane to refresh the specified
/// property values in the toolpart user interface.
/// </summary>
public override void SyncChanges()
{
// sync with the new property changes here
}

/// <summary>
/// Called by the tool pane if the user discards changes
/// to the selected Web Part.
/// </summary>
public override void CancelChanges()
{
}
/// <summary>
/// Render this Tool part to the output parameter
/// specified.
/// </summary>
/// <param name="output">
/// The HTML writer to write out to
/// </param>
protected override void RenderToolPart(HtmlTextWriter output)
{
EnsureChildControls();
tbl.RenderControl(output);
// Establish a reference to the Web Part.
//SmartPart.SmartPart wp1 = (SmartPart.SmartPart)this.ParentToolPane.SelectedWebPart;
//output.Write("Enter your custom text: ");
//output.Write("<input name= '" + inputname);
//wp1.
//output.Write("' type='text' value='" +
// SPEncode.HtmlEncode(wp1.GetCustomProperty("ReportId").ToString()) + "'> <br>");

}

}
}


Nov 7, 2007 at 6:00 PM
tronncarson, were you every able to determine why you are showing blank values in the toolpart when in "modify web part"? I have not found how to correct this issue. Any ideas?
Jan 3, 2008 at 5:42 PM


ChetRCreacy wrote:
tronncarson, were you every able to determine why you are showing blank values in the toolpart when in "modify web part"? I have not found how to correct this issue. Any ideas?


No I wasn't I just have to re-enter all values each time I modify the web part...
Jan 5, 2008 at 4:09 AM
I believe that I know what you are describing above. I think what you need to do mark up your properties with the <WebPartPages.WebPartStorage(WebPartPages.Storage.Shared)> tag so that they look like this.

<ComponentModel.Browsable(False), ComponentModel.DefaultValue(0), WebPartPages.WebPartStorage(WebPartPages.Storage.Shared)> _
Property ReportID() As Integer
Get
Return webReportID
End Get
Set(ByVal Value As Integer)
webReportID = Value
End Set
End Property
Mar 26, 2010 at 1:23 AM

This maybe helpful to someone

http://tallday.wordpress.com/2010/03/24/sharepoint-smartpart-toolparts/