Can a SharePoint list item have it's Targeted Audience calculated or otherwise automatically specified? - sharepoint

I want to show targeted (filtered) content from a list to users. I already have a column in the list that basically has the Target Audience value. This field is a multi-choice column (checkbox input) which I prefer over the current input field for Targeted Audiences.
To get audience filtering to work I unfortunately need to have the Targeted Audience field filled out for every list item. My current plan is to use a simple SharePoint designer workflow to set the Targeted Audiences field based on my other field, but I'm wondering if there is a better way. Am I just looking at this wrong?
Note that I know audiences can also be used to hide/show web parts, but that is not something I am interested in.

You could try and give this a whirl...
SPField audienceField = null;
try
{
audienceField = list.Fields[Microsoft.SharePoint.Publishing.FieldId.AudienceTargeting]
}
catch
{}
if(audienceField != null)
{
try
{
Audience siteAudience;
ServerContext context = ServerContext.GetContext(site);
AudienceManager audManager = new AudienceManager(context);
foreach (SPListItem item in list.Items)
{
string audienceName = item["fakeAudienceField"]; //should be the audience name created in SSP
siteAudience = audManager.GetAudience(audienceName);
Guid id = siteAudience.AudienceID;
item["Target Audiences"] = id.ToString()+";;;;";
item.Update();
}
}
catch
{}

I do not believe Target Audiences can be set up as a calculated field, in which case your options are workflow or a list item event receiver.
To set the audience field value, you can use AudienceManager.GetAudienceIDsAsText; Gary Lapointe has a post with example usage.

Maybe use a webpart to display the content of the list and use Audiences on the webpart sounds a solution easier to manage...

Related

Sharepoint webpart combobox of lists

I have a webpart that works off of a list but what I'm trying to do create a dropdown that contains a list of sharepoint lists so that when the user edits the page and selects 'modify shared webpart' they are able to choose a list item and that gets parsed back to the webpart.
Any examples or links to examples appreciated!
Thanks
Dan
What you are looking for is called a Toolpart. Take a look at this example for a tutorial on how to create one.
Overall, your general steps will be:
Create your custom Toolpart class inheriting from Microsoft.SharePoint.WebPartPages.ToolPart
In your custom Toolpart, override CreateChildControls, write the code to iterate over the lists in your SPWeb, and add those to a DropDownList
In your webpart, override GetToolParts and add your custom ToolPart so that it shows up in the right hand side
It sounds like you want to create a custom editor part. In the part you would have one dropdown that shows the names of the lists (you probably want to filter hidden and empty lists) and, when an item is selected from the list, a second dropdown shows the Title column of the items from the selected list.
Here's some code (edited here, so it will need to be cleaned up) to help you get started:
protected Page_Load(...)
{
if (IsPostBack) return;
var web = SPContext.Current.Web;
var query = from list in web.Lists
where list.Hidden == false && list.ItemCount == 0
select list;
DropDownList1.DataSource = query;
DropDownList1.DataTextField = "Title";
DropDownList1.DataBind();
}
protected DropDownList1_SelectedIndexChanged(...)
{
var web = SPContext.Current.Web;
var listName = DropDownList1.Text;
var list = web.Lists[listName];
var table = list.Items.GetDataTable();
DropDownList2.DataSource = table;
DropDownList2.DataTextField = "Title";
DropDownList2.DataValueField = "ID";
DropDownList2.DataBind();
}

SPList Item get value - ArgumentException

I have an SPListItem and I have an array of column names.
When I try to access the SPListItem values using the code below:
for(int i=0;i<arrColName.length;i++)
{
string tempValue = item[arrColName[i]].ToString();
// Works fine in case the the specific column in the list item is not null
// Argument exception - Values does not fall witing expected range
// exception in case the value //is null
}
I think that you used an SPQuery to get the list items and forgot to add the field into the viewfields property of SPQuery.
query.ViewFields = string.Format("<FieldRef Name=\"{0}\" Nullable=\"True\" />", mFieldName);
Usually when you test your program with the farm account the code will work, with normal users you get an ArgumentException.
Another problem/feature which causes ArgumentException is the new ListView Threshold. If th elist you try to access has too many items, this Exception is raised. A way to handle this is to increase the threshold with powershell for the list.
Not only check if item != null but also item["FieldName"] != null. Because if you will try to call .ToString() on null, you will get exception.
And if that field with internal name "FieldName" name does not exist, you will also get an exception. So you would probably try
SPFieldCollection fields = list.Fields;
foreach (SPListItem item in list.Items) {
if (fields.Contains("FieldName") && item["FieldName"] != null) {
string fieldValue = item["FieldName"].ToString();
}
}
I had a similar situation with custom cascade field (or column). I did it following way and it seemed to work for the custom field types.
item.Properties["Country"] = "Mexico"; // custom field
item.Properties["nCity"] = "Cancun"; // custom field
item["Document Descriptions"] = "Test document description.";
Note: I added item.Properties for the custom columns. No need to add properties for built in field type (else they don't work).
Does your array contain the internal names or the display names of the columns? If it's the latter you might try item[item.Fields[arrColName[i]].InternalName].ToStrinng(); instead.
Sharepoint Lists aren't stored as a array with a static size.
You have to use the built in sharepoint iterator to go through each element
For example:
SPList checklist = //Some initiliaztion
foreach (SPListItem item in checklist.Items){
//work
}
This will do work on each item in your SPlist
Edit:
Wrong advice, I didn't see the code until after the edit.
Maybe try a cast?
(String)item[colname]

Sharepoint event handling.. which column changed?

I'm writing an event handler to handle the updating of a particular SPItem in a list. The event is asynchronous and I get the SPEvenItemProperties without a problem. What I would like to find out is which of the SPItems columns' actually fired the event. Anyone have any idea how?
Thanks in advance.
Your answer depends a bit on from where and how the SPListItem is retrieved. In a regular list, you do not have access to the previous values of the item. If you turn on versioning, you can get access to the previous versions, depending on permissions, of course.
For a document library you can use the SPItemEventProperties.BeforeProperties to get the previous metadata for a document.
For a document library you can try something like this:
foreach (DictionaryEntry key in properties.BeforeProperties)
{
string beforeKey = (string)key.Key;
string beforeValue = key.Value.ToString();
string afterValue = "";
if (properties.AfterProperties[beforeKey] != null)
{
afterValue = properties.AfterProperties[beforeKey].ToString();
if (afterValue != beforeValue)
{
// Changed...
}
}
}
.b
I think the best way to do this would be to look through the BeforeProperties and AfterProperties of the SPItemEventProperties and check which fields have different values.
These contain the values of all fields of the item before and after the event occurred.

Sharepoint Custom List with TimeStamp Field

I'm making a custom SharePoint List. I need a TimeStamp Field, but the only available type, by default, is DateTime.
Any help?
I think you would need to create a custom field type so that you can control the display of a DateTime type and validation etc - see this blog post for more info
I had the same problem in Sharepoint 2010 and solved it. Posting in case someone else finds this useful :)
To achieve this one must use the "Calculated" columntype.
From GUI:
Create new column
Pick type "Calculated".
Select "Created" column and add to formula.
Save.
From code:
As far as I can tell, there is two options to achieve this:
Access the "Created" and either set it's ShowInDisplayForm property to true or add the column to a view (for example the DefaultView).
Create a calculated column that points to the "Created" column, just as the GUI-example does. The trick is to set the "Formula" & the "OutputType" properties.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists["test"];
string fieldName = list.Fields.Add("Timestamptest", SPFieldType.Calculated, false);
SPFieldCalculated field = list.Fields[fieldName] as SPFieldCalculated;
field.Formula = "=Created";
field.OutputType = SPFieldType.DateTime;
field.ShowInEditForm = false;
field.Update();
list.Update();
SPView defaultView = list.DefaultView;
defaultView.ViewFields.Add(field);
defaultView.Update();
}
}
});

Accessing SPLIstItem properties in SharePoint

I'm trying something very simple - accessing my SharePoint list's items and their properties.
However, SPListItem.Properties count is zero for all normal lists. Everything works as expected for document and pages libraries. So, if the list items are based on document type, all is good. If they are based on item, properties are not returned.
I've tried in two environments, with new sites created from OOTB publishing templates, with new lists which are based on OOTB content types etc. Always the same thing.
Right amount of SPListItems is always returned. Title and Name are fine. It's just that the .Properties hashtable is totally empty.
In desperation, I wrote a web part that outputs the following (ugly!) diagnostics.
foreach (SPList list in SPContext.Current.Web.Lists)
{
foreach (SPListItem item in list.Items)
{
Label label = new Label();
label.Text = "Name: " + item.Name + "Property count: " + item.Properties.Count;
this.Controls.Add(label);
}
}
The only observation is that it works exactly as I described earlier. I just share the code to show that this is the most basic operation imaginable.
Here is sample output - I've added the line breaks for readability ;-)
Name: Test Property count: 0
Name: default.aspx Property count: 21
Obviously item "Test" is an item based list item and default.aspx is a page.
Has anyone ever encountered anything like this? Any ideas?
item["FieldName"] is the canonical way to get a value of a metadata column in a SharePoint list. If you need to get the list of available fields for a SharePoint list, check the parent SPList object's Fields property which is a collection of the fields in this list. Each of those field objects will have a property called InternalName and that is what you should use to access its value when you are working with an instance of SPListItem.
Are you trying to get the field Values? Sadly, they are not strongly typed:
string ModifiedBy = (string)item["Author"];
To get the proper names of the fields (they have to be the internal names), go to the List and then List Settings. You will find the List of Columns there. Click on any Column Name to go to the Edit Page, and then look at the URL in the Address Bar of your Browser. At the very end, there should be a parameter "Field=Editor" or similar - that's your internal field name.
If you wonder why a field like "Test Field" looks strange, that is because Sharepoint encodes certain characters. A Space would be encoded to x0020 hence the Internal Name for "Test Field" is "Test_x0020_Field".
In order to get the proper field type to cast to:
string FieldType = item["Author"].GetType().FullName;
(The Intermediate Window in Visual Studio is tremendously helpful for this!)
I have found the following extension to the SPListItem class to be very helpful.
internal static class SharePointExtensions
{
internal static Dictionary<string, object> PropertiesToDictionary(this SPListItem item)
{
// NOTE: This code might be temping - but don't do it! ...itdoes not work as there are often multiple field definitions with the same Title!
// return item.Fields.Cast<SPField>().ToDictionary(fld => fld.Title, fld => item[fld.Title]);
Dictionary<string, object> dict = new Dictionary<string, object>();
var fieldNames = item.Fields.Cast<SPField>().Select(fld => fld.Title).Distinct().OrderBy(sz => sz).ToArray();
foreach (fieldName in fieldNames)
dict.Add(sz, item[fieldName]);
return dict;
}
}
with it you can simply do:
item.PropertiesToDictionary()
...and you will have a nice Linq dictionary object that will work just the way you'd expect. Is it a little heavy-weight / low-performance? Sure. Are most people willing to make that trade-off? I think so...
Do you run SPListItem.Update() or .SystemUpdate() after setting the properties?
If you want to get an object out of a SPField of a SPListItem you've got to do like this:
SPField field = ((SPList)list).Fields.GetField("FieldName");
object fieldValue = field.GetFieldValue(((SPListItem)item)[field.Title].ToString());
The ListItem.Properties hashtable will be empty unless you assign to it.
SPListItem item = properties.ListItem;
item.Properties["Key"] = "value";
int total = item.Properties.Count;
Answer:
"total == 1"
SPList yourList = web.Lists["Your list name"];
string sColumnValue = oSPListItem[yourList.Fields["yourSiteColumn display
name"].InternalName].ToString();

Resources