Sitecore access layout definition programmatically - c#

I want to access the layout definition of an item so that I can access the renderings added to the item, and then access the datasources attached to said renderings. I can't seem to find a way to do this. The best I could do is access the __renderings field but I then found out that this is going to access the original rendering definition item rather than the specific, datasourced instance stored in the Design Layout.
This is on Sitecore 7.5 MVC
If it helps, this is what I tried doing:
// Get the default device
DeviceRecords devices = item.Database.Resources.Devices;
DeviceItem defaultDevice = devices.GetAll().Where(d => d.Name.ToLower() == "default").First();
// Get the rendering references for the default device
Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(defaultDevice);
// Get the required renderings
RenderingItem headerRenderingItem = null;
RenderingItem aboutRenderingItem = null;
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingItem = rendering.RenderingItem;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingItem = rendering.RenderingItem;
}
Assert.IsNotNull(headerRenderingItem, "no header rendering item found");
Assert.IsNotNull(aboutRenderingItem, "no about rendering item found");
// Get their datasources
ID headerDatasourceId = ID.Parse(headerRenderingItem.DataSource); // The datasource string is null as it is accessing the datasource definition item itself
ID aboutDatasourceId = ID.Parse(aboutRenderingItem.DataSource); // Same as above

The RenderingReference.RenderingItem refers to the rendering item in the /layout section. What you could do is use RenderingReference.Settings.Datasource.
So your code would look something like:
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingDatasourceId = rendering.Settings.Datasource;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingDatasourceId = rendering.Settings.Datasource;
}
Item headerRenderingDatasourceItem;
if (!string.IsNullOrEmpty(headerRenderingDatasourceId)
headerRenderingDatasourceItem = item.Database.GetItem(headerRenderingDatasourceId);

Related

C# Sitecore get inherited templates

I'm trying to find all templates that inherit a particular template through code. I have the ID of the base template (Base Web Page), and I'm iterating through all of the template items in Sitecore looking for items that inherit Base Web Page.
foreach (var item in templateItems)
{
var baseTemplates = item.Template.BaseTemplates.ToList();
foreach (var baseTemplate in baseTemplates)
{
if (baseTemplate.ID == templateItem.ID)
{
inheritors.Add(item.ID.ToString());
}
}
}
However, item.Template.BaseTemplates gives me a list of the root level base templates; instead of giving me Base Web Page, it gives me the templates that Base Web Page inherits from (Advanced, Appearance, Help, etc)
Therefore I don't know if the item is actually inheriting Base Web Page or not.
Is there a method to get directly inherited templates? How can I find all templates that inherit Base Web Page?
The part item.Template in the
var baseTemplates = item.Template.BaseTemplates.ToList();
line is incorrect.
item.Template returns /sitecore/templates/System/Templates/Template here, so you're checking for a BaseTemplate of Template template always.
Your code should be:
foreach (var item in templateItems)
{
var baseTemplates = new TemplateItem(item).BaseTemplates.ToList();
foreach (var baseTemplate in baseTemplates)
{
if (baseTemplate.ID == templateItem.ID)
{
inheritors.Add(item.ID.ToString());
}
}
}
And the better approach may be using LinkDatabase to find all the referrers of your item which link from BaseTemplate field like that:
var links = Sitecore.Globals.LinkDatabase.GetItemReferrers(templateItem, false);
foreach (var link in links)
{
if (link.SourceFieldID == Sitecore.FieldIDs.BaseTemplate)
{
inheritors.Add(link.SourceItemID.ToString());
}
}

Programatically created Sitecore items have no version, no content; "Current item does not have a version in English" C#

I'm creating an import tool that programatically creates items in Sitecore. The item gets created, but when I view it, it says 'The current item does not have a version in "English : English."' I put in using (new LanguageSwitcher("en-gb")) but that didn't fix it. The way my code works is that it looks for the folder that the item is supposed to be put in (all folders are based on year, e.g. 2016, 2017); if the folder doesn't exist, I create that folder before creating the item. This is my code:
protected void PublishRelease(PressReleaseItem release)
{
using (new LanguageSwitcher("en-gb"))
{
var year = release.ReleaseDate.Year;
// create year folder if it doesn't exist
var folderQuery = String.Format(PressReleaseYearFolderFastQuery, year);
Item folder = _db.SelectItems(folderQuery).ToList().FirstOrDefault();
if (folder == null)
{
var templateId = _templateFactory.GetTemplateId<IPressReleaseYearFolderItem>();
TemplateID pressReleaseFolderTemplateId = new TemplateID(templateId.ToID());
folder = _pressReleaseFolder.Add(year.ToString(), pressReleaseFolderTemplateId);
}
if (folder == null) return;
// add item to folder
var itemTemplateId = _templateFactory.GetTemplateId<IPRNewswirePressReleaseItem>();
TemplateID pressReleaseTemplateId = new TemplateID(itemTemplateId.ToID());
item = folder.Add(SanitizeHeadline(release.Headline), pressReleaseTemplateId);
if (item == null) return;
item.Fields.ReadAll();
item.Editing.BeginEdit();
try
{
item.Fields["External ID"].Value = release.ExternalId;
item.Fields["Active"].Value = release.Active.ToString();
item.Fields["Image Url"].Value = release.ImageUrl;
item.Fields["PDF Url"].Value = release.PdfUrl;
item.Fields["Description"].Value = release.SubHeadline;
item.Fields["Headline"].Value = release.Headline;
item.Fields["Date"].Value = release.ReleaseDate.ToString("d");
item.Fields["Longtext"].Value = release.Body;
item.Fields["Category"].Value = SetReleaseCategories(release.Category);
}
catch (Exception ex)
{
item.Editing.EndEdit();
}
item.Editing.EndEdit();
}
}
When I view the new item in Sitecore, it says it has no version in English; when I click to add a new version, all of the fields are blank.
I would have expected the code you have above to default to creating a new version in the en-GB language. Like Richard mentions, validate if your 'english' is set to 'en' or 'en-gb'. If your default English has a different code, you might have to update your language switcher.
Alternatively, have you tried doing something like below to force a version?
var result = item.Versions.AddVersion();
This would at least allow you to test if the version creation is working at all, though you shouldn't need it for a new item.

Updating a field item's value in a Sharepoint form via C# - value not displaying?

I'm having trouble with a field on my form displaying. It's a DateTime data type and is being used to track how many days an item has been at that stage of production. I tried converting the item.["DaysInInitation"] to an Int, to see if that would work but nothing displays still. Could anyone point me in the right direction? Here is my code:
ClientContext ctx = new ClientContext(URL);
ctx.Credentials = new SharePointOnlineCredentials(Username, password);
List list = ctx.Web.Lists.GetByTitle(ListName);
ListItemCollection items = list.GetItems(CamlQuery.CreateAllItemsQuery());
ctx.Load(items); // loading all the fields
ctx.ExecuteQuery();
foreach (var item in items)
{
// important thing is, that here you must have the right type
// i.e. item["Modified"] is DateTime
//item["fieldName"] = newValue;
if (item.Id == fo.docid)
{
item.["DaysInInitation"] = fo.ini_di;
item.Update();
}
// do whatever changes you want
item.Update(); // important, rembeber changes
}
ctx.ExecuteQuery(); // important, commit changes to the server

How to get the current active view in a region using PRISM?

I know that i can get all the registered views in a region with :
var vs = mRegionManager.Regions[RegionNames.MainRegionStatic].Views.ToList();
and i can see there is the following code :
mRegionManager.Regions[RegionNames.MainRegionStatic].ActiveViews
which is giving a list of Active View, but I'm having my region attached to a ContentControl which always has a single ActiveView. Am i misunderstood or is there a way to get the single active view?
var singleView = regionManager.Regions["MyRegion"].ActiveViews.FirstOrDefault();
var singleView = regionManager.Regions["MyRegion"].ActiveViews.FirstOrDefault();
This is not correct, as it will just bring whatever view that got activated first. not the currently active/visible view.
Can't find a direct solution though, that doesn't involve custom implementation on View or ViewModel.
Well, you could use the NavigationService Journal. It takes record of all the navigation that takes place in your application. So, you can get the name of the view like this:
string name = mRegionManager.Regions[RegionNames.MainRegionStatic].NavigationService.Journal.CurrentEntry.Uri;
Then you can get the view like this:
mRegionManager.Regions[RegionNames.MainRegionStatic].GetView(name);
Sweet Right? :)
Using Xamarin.Forms & Prism, this works well for me. Change the regionName, change the View Model base to yours.
public VisualElement GetCurrentRegionView()
{
var regionName = "MenuPageRegion";
var region = RegionManager.Regions[regionName];
var uri = region.NavigationService.Journal.CurrentEntry.Uri.OriginalString;
foreach (var view in region.ActiveViews)
{
var name = view.GetType().FullName;
if (name.EndsWith(uri))
return view;
}
return null;
}
public CommonViewModelBase GetCurrentRegionViewModel()
{
var view = GetCurrentRegionView();
if (view != null)
{
var binding = view.BindingContext;
if (binding is CommonViewModelBase model)
return model;
}
return null;
}

Retrieve all items from a SharePoint Field Choice Column

I am playing around with a SharePoint server and I am trying to programmatically add a service request to microsoft's call center application template. So far, I have had pretty good success. I can add a call for a specified customer and assign a specific support tech:
private enum FieldNames
{
[EnumExtension.Value("Service Request")]
ServiceRequest,
[EnumExtension.Value("Customer")]
Customer,
[EnumExtension.Value("Service Representative")]
ServiceRepresentative,
[EnumExtension.Value("Assigned To")]
AssignedTo,
[EnumExtension.Value("Software")]
Software,
[EnumExtension.Value("Category")]
Category
}
private void CreateServiceCall(string serviceCallTitle, string customerName, string serviceRep)
{
SPSite allSites = new SPSite(siteURL);
SPWeb site = allSites.AllWebs[siteName];
SPListItemCollection requestsList = site.Lists[serviceRequests].Items;
SPListItem item = requestsList.Add();
SPFieldLookup customerLookup = item.Fields[FieldNames.Customer.Value()] as SPFieldLookup;
item[FieldNames.ServiceRequest.Value()] = serviceCallTitle;
if (customerLookup != null)
{
using (SPWeb lookupWeb = allSites.OpenWeb(customerLookup.LookupWebId))
{
SPList lookupList = lookupWeb.Lists.GetList(new Guid(customerLookup.LookupList), false);
foreach (SPListItem listItem in lookupList.Items)
{
if (listItem[customerLookup.LookupField].ToString() != customerName) continue;
item[FieldNames.Customer.Value()] = new SPFieldLookupValue(listItem.ID, customerName);
break;
}
}
}
SPUserCollection userCollection = site.SiteUsers;
if (userCollection != null)
{
foreach (SPUser user in userCollection)
{
if (user.Name != serviceRep) continue;
item[FieldNames.AssignedTo.Value()] = user;
break;
}
}
item.Update();
site.Close();
allSites.Close();
}
I added two custom columns (category, software) to the default list:
I populated both of these columns inside of SharePoint, now I want to retrieve that data so I can use it in the code snippet I posted to assign the proper category/software etc to the call. I have not been able to get the list in the code, I have tried using a item["Software"], site.Lists["Software"] and a couple of others, but so far all I have come up is null.
Can anyone point me in the right direction for this? Thanks!
SPFieldMultiChoice and related fields have a Choices property:
SPFieldMultiChoice software = item.Fields[FieldNames.Software.Value()] as SPFieldMultiChoice;
StringCollection softwareChoices = software.Choices;
If you need to set a value on the field, use the SPFieldMultiChoiceValue type:
SPFieldMultiChoiceValue values = new SPFieldMultiChoiceValue();
values.Add("Choice 1");
values.Add("Choice 2");
item[FieldNames.Software.Value()] = values;

Categories

Resources