Tuesday, July 28, 2009
Wednesday, July 15, 2009
Feature ActivationDependencies
So I have two features
1. Workflow Feature
2. Association Feature
the workflow feature look like below
Scope="Site"
ReceiverAssembly="Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
ReceiverClass="Microsoft.Office.Workflow.Feature.WorkflowFeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/">
WORKFLOW.xml
CodeBesideClass="ASSEMBLY.Workflow1"
CodeBesideAssembly="ASSEMBLY, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6e563d29ec4ce4ae"
TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
ModificationUrl="_layouts/ModWrkflIP.aspx">
WORKFLOWUPDATE.xml
CodeBesideClass="ASSEMBLY.UpdateForumFields"
CodeBesideAssembly="ASSEMBLY, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6e563d29ec4ce4ae"
TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
ModificationUrl="_layouts/ModWrkflIP.aspx">
FEATURE 2-->
Description="Feature Receiver for Attaching WFs"
Version="1.0.0.0"
Scope="Web"
ReceiverAssembly="ASSEMBLY2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3b623d2d8fcb1e2a"
ReceiverClass="ASSEMBLY2.DiscussionFeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/"
>
Associating workflow with List, SPWorkflowAssociation, CreateListAssociation
I have already discuss about creating feature receiver, so just focusing here is the SPWorkflowAssociation and CreateListAssociation.
In FeatureActivated method call this method with listInstance, string containig WF GUID, a workfow Association name and the web.
public void AddDFWorkflow(SPList myList, string workflowTemplateGuid, string workflowAssocName, SPWeb web)
{
//myList // List to associate workflow to
SPList historyList = null; // Workflow history list
SPList taskList = null; // Workflow tasks list
//workflowTemplateGuid // Workflow template Guid
SPWorkflowTemplate workflowTemplate = null; // Workflow template
SPWorkflowAssociation workflowAssociation = null; // Workflow association
//workflowAssocName // Workflow association name
workflowTemplate = web.WorkflowTemplates[new Guid(workflowTemplateGuid)];
try
{
historyList = web.Lists["Workflow History"];
}
catch (ArgumentException exc)
{
// Create workflow history list
Guid listGuid = web.Lists.Add("Workflow History", "", SPListTemplateType.WorkflowHistory);
historyList = web.Lists[listGuid];
historyList.Hidden = true;
historyList.Update();
}
try
{
taskList = web.Lists["Workflow Tasks"];
}
catch (ArgumentException exc)
{
// Create workflow tasks list
Guid listGuid = web.Lists.Add("Workflow Tasks", "", SPListTemplateType.Tasks);
taskList = web.Lists[listGuid];
taskList.Hidden = true;
taskList.Update();
}
web.AllowUnsafeUpdates = true;
try
{
// Create workflow association
workflowAssociation = SPWorkflowAssociation.CreateListAssociation(workflowTemplate, workflowAssocName, taskList, historyList);
// Set workflow parameters
workflowAssociation.AllowManual = false;
workflowAssociation.AutoStartCreate = false;
workflowAssociation.AutoStartChange = false;
// Add workflow association to my list
myList.AddWorkflowAssociation(workflowAssociation);
// Enable workflow
workflowAssociation.Enabled = true;
}
catch (Exception ex)
{ }
finally
{
web.AllowUnsafeUpdates = false;
}
}
In feature deactivated method call this method
public void RemoveDFWorkflow(SPList myList, string workflowAssocName, SPWeb web)
{
try
{
if (myList.WorkflowAssociations.Count > 0)
{
SPWorkflowAssociation _association = null;
foreach (SPWorkflowAssociation association in myList.WorkflowAssociations)
{
if (association.Name.Equals(workflowAssocName))
{
_association = association;
break;
}
}
if (_association != null)
myList.RemoveWorkflowAssociation(_association);
myList.Update();
}
}
catch (Exception ex)
{}
}
Enjoy!!!
Starting workflow Programmatically using object model SPWorkflowAssociationCollection , SPWorkflowAssociation, SPWorkflowManager
I have earlier discuss about creating event receiver and how to associate it with List. Lets focus here for now on starting the workflow
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
base.ItemAdded(properties);
if (isGlobalMailAllowed(properties))
{
//Mails are allowed at site level, start workflow to send mails
StartThisWorkflow(properties, strWorkflowAlertGUID);
}
}
catch (Exception ex)
{}
}
///
/// Starts a workflow associated to a list programmatically.
///
///
///
private void StartThisWorkflow(SPItemEventProperties properties, string strWorkflowID)
{
try
{
SPListItem listItem = properties.ListItem;
SPWeb web = properties.OpenWeb(); //Following best programming practices for Event handler to get spweb object
SPSite site = web.Site;
SPWorkflowManager manager = site.WorkflowManager;
SPList parentList = listItem.ParentList;
SPWorkflowAssociationCollection associationCollection = parentList.WorkflowAssociations;
LookupAndStartWorkflow(listItem, manager, associationCollection, strWorkflowID);
}
catch (Exception ex)
{}
}
///
/// Lookup and start the workflow.
///
///
///
///
///
private static void LookupAndStartWorkflow(SPListItem listItem, SPWorkflowManager manager,
SPWorkflowAssociationCollection associationCollection,
string workflowId)
{
foreach (SPWorkflowAssociation association in associationCollection)
{
Guid workflowGuid = new Guid(workflowId);
if (association.BaseId == workflowGuid)
{
string data = association.AssociationData;
SPWorkflow wf = manager.StartWorkflow(listItem, association, data);
}
}
}
Thanks to the miguelisidoro @
http://blogit.create.pt/blogs/miguelisidoro/archive/2008/07/05/SharePoint-2007-_2D00_-Start-a-Workflow-Programmatically.aspx
Cheers!!!
ListItemCollectionPosition, PagingInfo, SPQuery and paging in SharePoint
Finally got time to post after many days, hope to write all important stuff today..
Using inbuilt paging provided by SPListItemCollectionPosition, used with SPQuery....
I have used treeview control and am providing paging control (prev and next) options to it. Next will take it to the next set of paged responses. Using ajax to avoid post backs.
Lets create the webpart
protected TreeView tvSample;
LinkButton lnkBtnNextPage;
LinkButton lnkBtnPrevPage;
UpdatePanel updatePanelMain;
ArrayList arrListPrevPages;
private uint intPageSize;
private int intTopicID;
[WebBrowsable(true)]
[Personalizable(PersonalizationScope.Shared)]
[WebDescription("configure the Discussion tree per page size")]
[Category("Discussion Tree Properties")]
public uint PageSize
{
get
{
if (intPageSize == 0)
return 2;
else
return intPageSize;
}
set { intPageSize = value; }
}
[WebBrowsable(true)]
[Personalizable(PersonalizationScope.Shared)]
[WebDescription("configure the Discussion tree topic display")]
[Category("Discussion Tree Properties")]
public int TopicID
{
get {
if (intTopicID == 0)
return 125;
else
return intTopicID;
}
set { intTopicID = value; }
}
[Personalizable(PersonalizationScope.User)]
public string TreeRenderedVS
{
get { return Convert.ToString(ViewState["TreeRenderedVS"]); }
set { ViewState["TreeRenderedVS"] = value; }
}
[Personalizable(PersonalizationScope.User)]
public ArrayList ArrListPrevPages
{
get { return (ArrayList)ViewState["ArrListPrevPagesVS"]; }
set { ViewState["ArrListPrevPagesVS"] = value; }
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
FixFormAction();
this.updatePanelMain = new UpdatePanel();
this.updatePanelMain.ID = "updatePanelMain";
this.tvSample = new TreeView();
tvSample .ID = "responsesTreeView";
tvSample .CssClass = "TreeView1";
tvSample .Width = 950;
tvSample .ExpandImageToolTip = "Click here to expand";
tvSample .CollapseImageToolTip = "Click here to collapse";
tvSample .ExpandImageUrl = "bluearrow.gif";
tvSample .CollapseImageUrl = "_layouts/redarrow.gif";
tvSample .ParentNodeStyle.VerticalPadding = 0;
tvSample .NodeStyle.ChildNodesPadding = 0;
tvSample .NodeStyle.NodeSpacing = 0;
tvSample .NodeStyle.VerticalPadding = 0;
tvSample .NodeStyle.Width = Unit.Pixel(950);
tvSample .ToolTip = "";
tvSample.EnableClientScript = false;
this.tvSample.TreeNodePopulate += new TreeNodeEventHandler(Node_Populate);
TreeNode node = new TreeNode("Discussion","0");
tvSample.Nodes.Add(node);
this.lnkBtnNextPage = new LinkButton();
this.lnkBtnNextPage.ID = "lnkBtnNextPage";
this.lnkBtnNextPage.Text = "Next";
this.lnkBtnNextPage.Click += new EventHandler(lnkBtnNextPage_Click);
this.lnkBtnPrevPage = new LinkButton();
this.lnkBtnPrevPage.Text = "Previous";
this.lnkBtnPrevPage.ID = "lnkBtnPrevPage";
lnkBtnPrevPage.Click += new EventHandler(lnkBtnPrevPage_Click);
this.updatePanelMain.ContentTemplateContainer.Controls.Add(this.tvSample);
this.updatePanelMain.ContentTemplateContainer.Controls.Add(this.lnkBtnPrevPage);
this.updatePanelMain.ContentTemplateContainer.Controls.Add( new LiteralControl(" "));
this.updatePanelMain.ContentTemplateContainer.Controls.Add(this.lnkBtnNextPage);
this.Controls.Add(this.updatePanelMain);
if (TreeRenderedVS.Equals(String.Empty))
{
TreeRenderedVS = "Yes";
populateNodes();
}
arrListPrevPages = new ArrayList();
lnkBtnPrevPage.Attributes.Add("style", "display:none;");
}
{
base.EnsureChildControls();
base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
}
private void FixFormAction()
{
if (this.Page.Form != null)
{
string formOnSubmitAtt =
this.Page.Form.Attributes["onsubmit"];
if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
{
this.Page.Form.Attributes["onsubmit"] =
"_spFormOnSubmitWrapper();";
}
}
ScriptManager.RegisterStartupScript(this, typeof(VoicesDF), "UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action;_spSuppressFormOnSubmitWrapper=true;", true);
}
Now get treeview populated using the following code, I am using onDemand population of child nodes
protected void populateNodes()
{
tvSample.Nodes.Clear();
TreeNode tnodeDis = new TreeNode("Discussion", "0");
tnodeDis.Expand();
tvSample.Nodes.Add(tnodeDis);
DataTable dtReplies = GetActiveResponsesLevel0("MostRecent", Convert.ToInt32(TopicID), "Discussion Forum");
for (int i = 0; i < newnode =" new" populateondemand =" true;" selectaction =" TreeNodeSelectAction.None;">public void Node_Populate(object sender, System.Web.UI.WebControls.TreeNodeEventArgs e)
{
if (e.Node.ChildNodes.Count == 0)
{
switch (e.Node.Depth)
{
case 0:
FillRootResp(e.Node);
break;
default:
FillReplies(e.Node);
break;
}
}
}
public void FillRootResp(TreeNode node)
{
DataTable dtReslev0 = GetActiveResponsesLevel0("MostRecent", Convert.ToInt32("125"), "Discussion Forum");
for (int i = 0; dtReslev0 != null && i < newnode =" new" populateondemand =" true;" selectaction =" TreeNodeSelectAction.None;">public void FillReplies(TreeNode node)
{
DataTable dtReplies = GetActiveReplies("MostRecent", Convert.ToInt32(node.Value), "Discussion Forum");
for (int i = 0; dtReplies != null && i < newnode =" new" populateondemand =" true;" selectaction =" TreeNodeSelectAction.None;">public DataTable GetActiveResponsesLevel0(string view, int QuestionId, string messageBoardName)
{
DataTable dtResponses = null;
using (SPSite site = new SPSite(strMysiteURL))
{
using (SPWeb web = site.OpenWeb(strMyWebURL))
{
SPQuery query;
string orderByQuery = string.Empty;
query = new SPQuery();
StringBuilder queryText = new StringBuilder();
queryText.Append("
queryText.Append("
queryText.Append("
queryText.Append(QuestionId.ToString());
queryText.Append("
queryText.Append("
queryText.Append("
queryText.Append("
if (view.Equals("MostRecent"))
{
orderByQuery = "
}
else if (view.Equals("Author"))
{
orderByQuery = "
}
else if (view.Equals("Title"))
{
orderByQuery = "
}
queryText.Append(orderByQuery);
query.Query = queryText.ToString();
//query.InnerXml = string.Empty;
query.ViewAttributes += " Scope=\"Recursive\"";
query.RowLimit = PageSize; // that is our page size
SPListItemCollection itemColl = null; //This will be used for paging
if (Page.Session["ListItemCollectionPosition"] == null && Convert.ToString(Page.Session["ListItemCollectionPosition"]).Equals(string.Empty))
{
itemColl = web.Lists[messageBoardName].GetItems(query);
}
else
{
//query.ListItemCollectionPosition = (SPListItemCollectionPosition)Page.Session["ListItemCollectionPosition"]; //U cannot store ListItemCollectionPosition in Session (NSer)
string strPagingInfo = Convert.ToString(Page.Session["ListItemCollectionPosition"]); //Compiled paging info, of next page... get it from session
SPListItemCollectionPosition itmPosn = new SPListItemCollectionPosition(strPagingInfo); //Atleast the contructor is helpful here
query.ListItemCollectionPosition = itmPosn; //Update the spquery object so as to query this sessioned page
itemColl = web.Lists[messageBoardName].GetItems(query); //retrieve the paged data
}
dtResponses = itemColl.GetDataTable();
if (itemColl.ListItemCollectionPosition != null)
{
Page.Session["ListItemCollectionPositionNext"] = itemColl.ListItemCollectionPosition.PagingInfo; //Store the paginginfo in session so for next time it will be used, instead of new SPQuery
lnkBtnNextPage.Attributes.Add("style", "display:inline;");
}
else
{
Page.Session["ListItemCollectionPositionNext"] = null;
lnkBtnNextPage.Attributes.Add("style", "display:none;");
}
Page.Session["Added"] = "true";
}
}
// });
if (dtResponses != null)
return dtResponses;
else
return null;
}
//For all child replies
public static DataTable GetActiveReplies(string view, int QuestionId, string messageBoardName)
{
DataTable dtResponses = null;
using (SPSite site = new SPSite(strMySiteURL))
{
using (SPWeb web = site.OpenWeb(strMyWebURL))
{
SPQuery query;
string orderByQuery = string.Empty;
query = new SPQuery();
StringBuilder queryText = new StringBuilder();
queryText.Append("
queryText.Append("
queryText.Append("
queryText.Append(QuestionId.ToString());
queryText.Append("
queryText.Append("
queryText.Append("
queryText.Append("
if (view.Equals("MostRecent"))
{
orderByQuery = "
}
else if (view.Equals("Author"))
{
orderByQuery = "
}
else if (view.Equals("Title"))
{
orderByQuery = "
}
queryText.Append(orderByQuery);
query.Query = queryText.ToString();
//query.InnerXml = string.Empty;
query.ViewAttributes += " Scope=\"Recursive\"";
dtResponses = web.Lists[messageBoardName].GetItems(query).GetDataTable();
}
}
// });
if (dtResponses != null)
return dtResponses;
else
return null;
}
//Below two function for formatting the node and adding some details to it.
private string GetFormattedText(DataRow dr)
{
StringBuilder nodeText = new StringBuilder();
string responseTitle = string.Empty;
string responseBody = string.Empty;
string authorPId = string.Empty;
string createdDate = string.Empty;
string userName = string.Empty;
int comments = 0;
string totalResponse = string.Empty;
bool boolDisplayYourName = true;
const string strAnonymous = "Anonymous";
responseTitle = dr["Body"].ToString();
authorPId = dr["AuthorPId"].ToString();
if (dr["AuthorName"] != null)
userName = dr["AuthorName"].ToString();
createdDate = Convert.ToDateTime(dr["created"].ToString()).ToShortDateString();
string strDisplayYourName = dr["DisplayYourName"].ToString().Trim();
if (strDisplayYourName.Trim() == "1")
boolDisplayYourName = true;
else if (strDisplayYourName.Trim() == "0")
boolDisplayYourName = false;
totalResponse = responseTitle;
totalResponse += " (" + comments.ToString() + ") ";
totalResponse += " (" + createdDate + ") ";
if (comments > 0)
{
if (boolDisplayYourName == true)
totalResponse += "" + " by " + userName + "";
else
totalResponse += "" + " by " + strAnonymous + "";
}
else
{
if (boolDisplayYourName == true)
totalResponse += "" + " by " + userName + "";
else
totalResponse += "" + " by " + strAnonymous + "";
}
nodeText.Append(" ");
");
nodeText.Append(" "); ");
if (comments > 0)
nodeText.Append(" ");
else
nodeText.Append(" "); ");
nodeText.Append(totalResponse);
nodeText.Append("
nodeText.Append("
nodeText.Append("
return nodeText.ToString();
}
private string GetFormattedText(DataRow dr, int iDepth)
{
StringBuilder nodeText = new StringBuilder();
string responseTitle = string.Empty;
string responseBody = string.Empty;
string authorPId = string.Empty;
string createdDate = string.Empty;
string userName = string.Empty;
int comments = 0;
string totalResponse = string.Empty;
bool boolDisplayYourName = true;
const string strAnonymous = "Anonymous";
responseTitle = dr["Body"].ToString();
authorPId = dr["AuthorPId"].ToString();
if (dr["AuthorName"] != null)
userName = dr["AuthorName"].ToString();
createdDate = Convert.ToDateTime(dr["created"].ToString()).ToShortDateString();
string strDisplayYourName = dr["DisplayYourName"].ToString().Trim();
if (strDisplayYourName.Trim() == "1")
boolDisplayYourName = true;
else if (strDisplayYourName.Trim() == "0")
boolDisplayYourName = false;
totalResponse = responseTitle;
totalResponse += " (" + comments.ToString() + ") ";
totalResponse += " (" + createdDate + ") ";
if (comments > 0)
{
if (boolDisplayYourName == true)
totalResponse += "" + " by " + userName + "";
else
totalResponse += "" + " by " + strAnonymous + "";
}
else
{
if (boolDisplayYourName == true)
totalResponse += "" + " by " + userName + "";
else
totalResponse += "" + " by " + strAnonymous + "";
}
if (iDepth > 0)
nodeText.Append(" ");
else
nodeText.Append(" ");
");
nodeText.Append(" "); ");
if (comments > 0)
nodeText.Append(" ");
else
nodeText.Append(" "); ");
nodeText.Append(totalResponse);
nodeText.Append("
nodeText.Append("
nodeText.Append("
return nodeText.ToString();
}
The important method is GetActiveResponsesLevel0 for paging, other method mostly help with treeview.
Happy programming!!!
