I am using SharePoint Foundation 2010 and I would like to create a multilevel navigation. (Similar to what the publishing site allows in SharePoint Standard. I realize that this could probably be built using a custom sitemap provider, which I have looked into.
The kicker here, is that I would like for it only show the pages and sites in which the logged in user has permissions to.
Currently, I have began developing a web part. Inside this web part I have written some c# code to loop through and get all the sites and subpages ( and check if the user has permissions) and then add them to a label. Eventually I would like to add them to either an asp:menu or create a and then use some css or jquery to manipulate it to do the drop down features.
Here is some of my code:
using (SPWeb oWebsite = new SPSite(webUrl).OpenWeb())
{
SPWebCollection collWebsite = oWebsite.Webs;
foreach (SPWeb subSite in collWebsite)
{
if (subSite.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName, SPBasePermissions.Open))
{
Label1.Text += SPEncode.HtmlEncode(subSite.Title) + "<BR>";
}
SPList pagelist = subSite.Lists["Site Pages"];
foreach (SPListItem item in pagelist.Items)
{
if (item.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser, SPBasePermissions.Open))
{
Label1.Text += item.Name + "<BR>";
}
}
Label1.Text += "<BR><BR>";
subSite.Close();
}
Label1.Text += "<BR><BR><BR><BR>";
}
}
Instead of adding the site or page to the label, here is where I would like to create the list. The ultimate goal would be to place this web part onto the masterpage and allow for it to give the users some navigation based on permissions.
I also found some css to allow the multilevel navigation to work by adding elements simply as a inside of an The only issue here is that once I placed this onto the masterpage, The 2nd level displayed when I hovered over the first item, but would disappear upon moving my mouse there. (This worked great when the webpart was placed onto a page itself)
Am I on the right track here or is there another method that may work just as well or even better?
TIA.
SPSecurity.RunWithElevatedPrivileges(delegate
{
SPSite oSiteCollection = SPContext.Current.Site;
using (SPWeb oWebsite = new SPSite(webUrl).OpenWeb())
{
SPWebCollection collWebsite = oWebsite.Webs;
foreach (SPWeb subSite in collWebsite)
{
var newItem = new MenuItem();
if (subSite.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName, SPBasePermissions.Open))
{
newItem.NavigateUrl = subSite.Url;
newItem.Text = SPEncode.HtmlEncode(subSite.Title);
newItem.Value = SPEncode.HtmlEncode(subSite.Title);
}
SPList pagelist = subSite.Lists["Site Pages"];
foreach (SPListItem item in pagelist.Items)
{
if (item.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser, SPBasePermissions.Open))
{
var subItem = new MenuItem();
subItem.Value = SPEncode.HtmlEncode(item.Name);
subItem.Text = SPEncode.HtmlEncode(item.Name);
subItem.NavigateUrl = item.Url;
newItem.ChildItems.Add(subItem);
}
}
mnNAv.Items.Add(newItem);
subSite.Close();
}
}
});
Related
I have a form in my Xamarin project that its result is something like that:
Basically there is a header (1) and a body of this form (2). The header is quite simple build with AbsoluteLayout.
For creating the body (2) I've created my component to show a tab control and then for each tab a specific grid with images and text. For each section, I'm checking in the database how many records there are for it and change the text. This activity is very long and I'm trying to understand why and how I can improve speed.
Then I should cut the corner to add later in my page the tab control so the user can see immediately the header and after few second all page. The code is like the following:
public class MyPage : WaitingPage
{
public MyPage(Card card)
{
LoadingMessage = "Loading...";
ShowLoadingFrame = true;
ShowLoadingMessage = true;
ShadeBackground = true;
WaitingOrientation = StackOrientation.Vertical;
IsWaiting = true;
StackLayout stackPage = new StackLayout() {
BackgroundColor = Color.FromHex("#fff"),
Children = {
ShowHeader(card),
}
};
Content = stackPage;
Task.Yield();
Task.Run(async () => {
Content = await ShowDetails(card);
});
IsWaiting = false;
}
}
I tried different ways to add the content from await ShowDetails(card); but nothing happens. Basically the content doesn't change unless await ShowDetails(card); is executed. I discovered Task.Yield(); (you can wait the page is rendered and showed and then continue) but in this case doesn't work. And also WaitingPage doesn't show the message.
Any suggestions or help? Thank you in advance
I have some ASP.NET code that has an SSRS report control on page. The web application is hosted on a different server than where SSRS is hosted. The problem I'm having is when I pull up the report in Internet Explorer the date picker control is not showing the calendar and if I try to pull up the report in Chrome the date picker control doesn't show up at all. If I type dates into the text boxes, the report works just fine but, we would really like to be able to use the date picker control.
Any ideas as to what could be wrong?
I believe this question to be different from those asked before because I am not only asking about non-IE browsers, but also asking about an issue with IE.
The date picker control does not display the calendar in IE when the user clicks on the control.
Wayne E. Pfeffer
------ Edit to add code example ------
The aspx code is:
<rsweb:ReportViewer ID="ReportViewer1" runat="server" ProcessingMode="Remote" Width="100%" Height="100%" AsyncRendering="False">
</rsweb:ReportViewer>
<asp:ScriptManager ID="ScriptManager1" runat="server">
There is a drop down list where a report is chosen and this is the code for loading the report into the report viewer:
protected void loadViewer(string report) {
ReportViewer1.ProcessingMode = ProcessingMode.Remote;
IReportServerCredentials irsc = new CustomReportCredentials(
ConfigurationManager.AppSettings["ReportUser"],
ConfigurationManager.AppSettings["ReportPswd"],
ConfigurationManager.AppSettings["ReportDomain"]);
ReportViewer1.ServerReport.ReportServerCredentials = irsc;
ReportViewer1.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["ReportURL"]);
ReportViewer1.ServerReport.ReportPath = ConfigurationManager.AppSettings["ReportPath"] + report;
ReportViewer1.SizeToReportContent = true;
//Get the list of account IDs that the user has viewothertransactions at
List<string> vaIds = new List<string>();
string votAccts = (String)Session["votAccounts"];
string[] aIds = votAccts.Split(',');
foreach (var aId in aIds)
{
vaIds.Add(aId);
}
//Create the list of account ids where the user can only see its orders
List<DropdownOption> acclist = (List<DropdownOption>)Session["searchAccounts"];
string acctIds = "";
if (null != acclist)
{
for (int i = 0; i < acclist.Count; i++)
{
if (!vaIds.Contains(acclist[i].Id))
{
acctIds += acclist[i].Id + ",";
}
}
if (acctIds.Length > 0)
{
acctIds = acctIds.Substring(0, acctIds.Length - 1);
}
}
Users user = (Users) Session["userObject"];
ReportParameter userid = new ReportParameter("Userid", user.Id.ToString());
ReportParameter votAccounts = new ReportParameter("VotAccounts", votAccts);
ReportParameter accounts = new ReportParameter("Accounts", acctIds);
log.Debug("Requesting report '" + report + "'. Parameters - Userid=" + user.Id + " VotAccounts=" + votAccts + " Accounts=" + acctIds);
ReportViewer1.ServerReport.SetParameters(new ReportParameter[] { userid, votAccounts, accounts });
ReportViewer1.ServerReport.Refresh();
}
When using Internet Explorer 11 you could try Compatibility Mode .
Try pressing F12 whilst on the page to see what browser emulation is used.
I recently encountered this problem on IE and tracked down the issue to a javascript function registered by the report control. The javascript function adds a prototype method "Show" to the "DropDownParamClass". Inside the function is a line of code that checks for the presence of a "FORM" tag and if it's not there abandons the function...
// do not show the drop down if the frame has not yet been aded to the form tag
if (floatingIFrame.parentNode.tagName.toUpperCase() != "FORM")
return;
In my case the floatingIFrame.parentNode.tagName was returning a "DIV"... As a fix I've simply overwritten the DropDownParamClass.prototype.Show function with a slightly revised version (not the new explaining variable "readyToShowCalendar" which checks for either a DIV or a FROM tag), see below...
<script language="javascript" type="text/javascript">
if (typeof (window.DropDownParamClass) !== "undefined") {
//Fix for bug in report viewer control resulting in the Calendar Control not displaying when the calendar icon is clicked.
window.DropDownParamClass.prototype.Show = function () {
var floatingIFrame = document.getElementById(this.m_floatingIframeID);
// do not show the drop down if the frame has not yet been added to the form tag
var readyToShowCalendar = "FORM,DIV".indexOf(floatingIFrame.parentNode.tagName.toUpperCase()) > -1;
if (!readyToShowCalendar) return;
// position the drop down. This must be done before calling show base. Otherwise,
// a scroll bar is likely to appear as a result of showBase which would make the
// position invalid.
var newDropDownPosition = this.GetDropDownPosition();
floatingIFrame.style.left = newDropDownPosition.Left + "px";
floatingIFrame.style.top = newDropDownPosition.Top + "px";
this.ShowBase();
// poll for changes in screen position
this.StartPolling();
};
}
</script>
This script was then simply placed just underneath the initial tag on the page. After this the calendar control then seems to open as expected when clicking the calendar icon.
I use a System.Web.UI.WebControls.Menu to build and present a user menu. Loading the menu requires considerable database activity and takes about 1.4 seconds, so I am looking for ways to cache the menu across page turns. If I keep a SessionVariable["ThisMenu"] that contains the menu control, the value of ThisMenu is correct across page turns; however, I cannot set the actual control on the page successfully.
If I try this code, it compiles and executes, but nothing appears in the HTML output:
System.Web.UI.WebControls.Menu ctlMasterMenu = (System.Web.UI.WebControls.Menu)GetControl("ctlMasterMenu");
if (ctlMasterMenu != null)
{
if (ThisMenu != null)
{
ctlMasterMenu = ThisMenu;
}
else
{
LoadPageMenu((System.Web.UI.WebControls.Menu)ctlMasterMenu); // Sets ThisMenu
}
}
If I try this code, it executes, but as it adds a MenuItem to ctlMasterMenu, it removes the item from ThisMenu. The result is that after a few page turns, the menu is empty.
System.Web.UI.WebControls.Menu ctlMasterMenu = (System.Web.UI.WebControls.Menu)GetControl("ctlMasterMenu");
if (ctlMasterMenu != null)
{
if (ThisMenu != null)
{
List<MenuItem> items = new List<MenuItem>();
for (int i = 0; i < ThisMenu.Items.Count; i++)
{
items.Add(ThisMenu.Items[i]);
}
ctlMasterMenu.Items.Clear();
foreach (MenuItem item in items)
{
ctlMasterMenu.Items.Add(item); // Causes item to be removed from ThisMenu
}
}
else
{
LoadPageMenu((System.Web.UI.WebControls.Menu)ctlMasterMenu);
}
}
There must be a simple way that works.
Consider caching or reworking your database query. Caching the menus will likely result in storing additional data on the server or client via ViewState. The source of your menus is your data so you should start there.
Store the actual data that builds the menu in cache, and build the menu every time from this cached data. Disable viewstate to save on performance. Don't store the menu or menu items themselves.
I thought this was straight forward, but i have a link button, and I do this in the click event:
myContainer.Controls.Add( new FileUpload());
I expect 1 new file control upload to be spawned in the container for each click, however, I always get 1. What do I need to do to have multiple file upload controls?
Since the control was added dynamically, it does not survive the postback. This means that you have to add the file upload (or any other dynamically added control) again in the preinit event to be able to have its values populated and to use it later on in the page life cycle.
Sounds like you are trying to be able to upload multiple files. You may want to add the file uploads with jQuery and use the Request.Files property to get them on the back-end.
I agree with Becuzz's answer. Try this, there are better ways to do it, but this might help as well:
Add this to the "Load" event of your page
if (!IsPostBack) {
Session["UploadControls"] = null;
}
if (Session["UploadControls"] != null) {
if (((List<Control>)Session["UploadControls"]).Count > 0) {
foreach ( ctrl in (List<Control>)Session["UploadControls"]) {
files.Controls.Add(ctrl);
}
}
}
And also add this to the PreInit portion of your page:
string ButtonID = Request.Form("__EVENTTARGET");
if (ButtonID == "Button1") {
FileUpload NewlyAdded = new FileUpload();
List<Control> allControls = new List<Control>();
if (Session["UploadControls"] != null) {
if (((List<Control>)Session["UploadControls"]).Count > 0) {
foreach ( ctrl in (List<Control>)Session["UploadControls"]) {
allControls.Add(ctrl);
//Add existing controls
}
}
}
if (!allControls.Contains(NewlyAdded)) {
allControls.Add(NewlyAdded);
}
Session["UploadControls"] = allControls;
}
And add this to your HTML. This can be anything of course:
<div id="files" runat="server">
</div>
I use the "__EVENTTARGET" value to know what caused the postback, so that you don't get unwanted Upload controls.
Good luck, and hopefully this helps.
Hanlet
I have a menu control (Menu1) and I want to add/remove items from the menu based on certain information I have stored about the authenticated user in the database. I'm not sure though how to access specific menu items from the menu control and remove them at runtime?
ASP.NET menus can be accessed via code behind. A menu declared in the markup, having the id 'Menu1' for example, could be accessed like so:
foreach (MenuItem item in Menu1.Items) {
if (item.NavigateUrl.Contains(pageName)) {
item.Selected = true;
item.Text = "customText";
}
// ...
}
In that example, the currently selected menu item is chosen according to the current page the menu is on. Just as well, the Items collection may be used to add or remove single menu items.
Note, on menu items, the ChildItems collection can be used to alter the submenu items collection.
More infos: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.menu.items.aspx
#Edit: made it more coherent with the data in the question
I wish you was more specific but I know that the notification for comments kinda sucks here. so if you could tell me exactly
what is the information you'll Add/Remove items based on ?
how are they're stored in the database (which means are they are stored in one of the membership tables ? in the profile's table ? or a custom table where the user is referenced in ?
what's the technique you imagine in your mind in plain English ?
I'm not sure though how to access
specific menu items from the menu
control and remove them at runtime?
A. Remove items:
Menu1.Items.Remove(Menu1.FindItem("Jobs"))
B. Add Items:
Menu1.Items.Add(new MenuItem("News"))
OR use this to specify the required
properties for the new added item:
MenuItem item = new MenuItem()
item.NavigateUrl =""
item.Text = "Child Test"
Menu1.Items.Add(mnuTestChild)
protected void Page_Load(object sender, EventArgs e)
{
con.ConnectionString = ConfigurationManager.ConnectionStrings["MyConString"].ConnectionString;
string selectCmd = "Select * from Pages where Status='"+1+"'";
SqlDataAdapter dap = new SqlDataAdapter(selectCmd,con);
DataSet ds = new DataSet();
dap.Fill(ds);
if (!Page.IsPostBack)
{
int x = 0;
string parent_id = "";
foreach (DataRow dr in ds.Tables[0].Rows)
{
parent_id = dr[0].ToString();
Menu1.Items.Add(new MenuItem(dr["Title"].ToString(), dr["URL"].ToString(), dr["ID"].ToString()));
}
x++;
}
}