Masterpage -> SubMasterPage -> Web Form...getting properties of Masterpage in sub pages - asp.net

I asked a related question on this yesterday, and was told what not to do, but not what I should do.
I've got a master page that I'll call "TheMaster". I've got 2 sub master pages "Sub1" and "Sub2". They both have a Masterpage directive of "TheMaster". Web Forms have a Masterpage directive of "Sub1" or "Sub2". These aren't the real names.
In "TheMaster", I figure out what page the user is on, find out where in the Web.sitemap they are, and using that, I have the Web.sitemap node and the parent and the parent's parent, if they all exist. I use this to build navigation dynamically and highlight the current page.
Now, our designers have several places this navigation appears. Top nav, sub nav, teritiary nav on the left, and a "breadcrumb" style showing home -> parentparentnode -> parentnode -> currentpage
I can NOT define all of this in "TheMaster" due to layout constraints.
So, in "TheMaster", I find their current node, and save that as a public property of "TheMaster" (along with several other pieces of info.
In Sub1, even though it is using "TheMaster" as it's masterpage, it does not appear to be able to find my public properties from "TheMaster".
Any ideas on how I can get this info to be available all the way through this house of cards?
I've tried
Page.Master.myProp (nope)
Parent.myProp (nope)
I can't think of anyything else to get this to work. "TheMaster" has basically no knowledge of "Sub1", so I can't set a property on Sub1 and have it go down the tree, and the nodes down the tree are apparently oblivious to their parents...???

Cast Parent or Page.Master to your actual MasterPage class.
((MyMaster)Page.Master).myProp // found!

Casting gets you there, but it isn't so clean nor maintainable in the long run. I've done very, very complex versions of this using a series of interfaces to abstract things. See this blog post for a simplified version with one layer. The trick to adding more layers is just adding some more interfaces and abstract classes as appropriate.

Related

Storing a view in Xamarin.Forms MvvmCross

I have an app with four main pages, switched through a tab bar (no "back" button).
One page has a lot of content (ScrollView) and takes quite a few seconds until it's rendered. I handle that by showing a "loading" overlay while the work is done. But for that specific page I'd like to keep the view alive, so that when the user switches to another page and comes back later, the page is ready without loading everything again.
I'm not sure how to do that in MvvmCross, though.
I did read the documentation and from what I understood the View Presenter would be the right way to do it, since the docs say:
"Another kind of presentation changes your app can request through
hints includes clearing / modifying the BackStack, changing a root
while maintaining the existent views, … possibilities are really
endless. Once again your app is king here!"
I guess I would need to create a custom MvxPresentationHint for that, but I don't quite get it :(
How or rather where would I access and store/load the View?
I'm generally still quite unfamiliar with MvvmCross (how it works under the hood) and especially customization of Mvx classes, even though I've been using it for a while.
Any explanation and preferably code examples beyond what's written in the documentation would be extremely appreciated!
It isn't meaningful to attempt to "store" a view in MVVM. The XF view is a representation of what will be created with native (e.g. "Android" or "iOS") widgets. Creating and measuring/laying out those native widgets is what is slow. MVVM View Presenter won't speed up that logic.
Instead of "store", you need "keep alive":
For a ContentPage called MyPage, when you create it, store it in a static variable. Then re-use that variable. If you never need more than one of these, you can store it in the class itself.
Modify the "code behind", MyPage.xaml.cs:
public partial class MyPage : ContentPage
{
// Singleton Pattern.
private static MyPage _it;
public static MyPage It {
get {
if (_it == null)
_it = new MyPage();
return _it;
}
}
// "private", because calling this directly defeats the purpose. Instead, use `MyPage.It`.
private MyPage()
{
InitializeComponent();
}
}
To create it, whereever you would put:
new MyPage()
instead put this:
MyPage.It
For instance, you might do PushAsync(MyPage.It);
This will always return the SAME INSTANCE of MyPage. So once it has been created, it keeps its state.
IMPORTANT: Note that the constructor is only called ONCE. Any code that needs to be done each time the page appears, put in override .. OnAppearing() method.
LIMITATION: Views "expect" to be part of the visual hierarchy when they are manipulated. If you attempt to alter the page or its view model while it is not on the screen, you may encounter problems. Those are beyond the scope of this answer - create a new StackOverflow question with the details of any problem you encounter.

Issues with wrapping PrismForms NavigationService

In PrismForms we got the problem, that the NavigationStack is empty after navigating to a new page. That means after using the hardware back-button on the SecondPage, the app is closed. Although the back-arrow in the header on Android isnt shown. If looking closely you can see the back-arrow for a short moment after the page is switched. I guess thats before the NavigationStack gets cleared.
To the first page we navigate with the following command in OnInitialized() in our App.xaml.cs which derives from PrismApplication.
NavigationService.NavigateAsync("NavigationPage/StartPage");
(If only Navigating to „StartPage“ here, the Stack doesnt get cleared.)
That has do to with PageNavigationService.ProcessNavigationForNavigationPage(...) calling
bool clearNavStack = GetClearNavigationPageNavigationStack(currentPage); and PageNavigationService.ProcessNavigationForContentPage(...) not.
From the StartPage to the next we navigate with NavigateAsync("SecondPage")“. Here the described behaviour appears.
For navigation we use a class which wraps the Prism NavigationService. We hold him as a property and get him via Unity in our constructor:
this.PrismNavigation = prismNavigation ?? throw new ArgumentNullException(nameof(prismNavigation));
The methods „NavigateAsync“ and „GoBackAsync“, etc. we just pass through.
This way we want to seperate our ViewModel-Project from references to XamarinForms to later be able to use the same ViewModels for for example a WPF-GUI.
Why is the stack beeing cleared by our own NavigationService? If we register the original Prism NavigationService in App.xaml.cs instead, navigating back works as expected again. We found the point in the framework and could avoid the clearing with a drity hack, but that’s against the navigation-logic implemented in PrismForms, but we don’t understand how to do it the correct way.
Every help appreciated!
We edited a few things to get it working after finding some interesting information by Brian Lagunas in the forlast-post here:
https://github.com/PrismLibrary/Prism/issues/591
Although the topic was about something else, it led to improvements for overwriting the Navigation Service.
Remember that in your viewModels the Navigation Service must be named "navigationService" by convention. Also we switched from just holding the Prism Navigation Service as a parameter to deriving from it as suggested in the link above.
public class MyNavigationService : UnityPageNavigationService

Add an Html Control in multiple parents in asp.net

I'm creating a new unordered list as follows:
Using htmlUL As New HtmlGenericControl("ul")
End Using
Before closing the 'Using' clause, the list has to be added in a parent control:
Using htmlUL As New HtmlGenericControl("ul")
'Some Code Here
parent1.Controls.Add(htmlUl)
End Using
Everything works fine until i add my control to more parents :
Using htmlUL As New HtmlGenericControl("ul")
'Some Code Here
parent1.Controls.Add(htmlUl)
parent2.Controls.Add(htmlUl) '<--- Only gets added in the last parent's collection
End Using
This behaviour is expected because every control is unique. But i need to add this list to more than one parents (it does not include any static ids in order to avoid conflicts)
ASP.NET does not support scenario like the very same control object used in several places. The reason here I believe is the problem with identification of the control later in the page life cycle - this control would have to render under different parents, and with different IDs, etc. Looks like a very complicated and dangerous use case.
However there are several workarounds written here and there to clone controls on the page. For example checkout these threads: Copy/Clone Control, A Custom Copy Control - Copies Any ASP.NET Control.
All that beign said, in your case the easiest thing is just to create new list for each parent control. You do not need to copy any specific properties or data whatsoever, so no need for cloning overhead done in the solutions above.

sharepoint 2010 cannot get global navigation nodes in code

I have sharepoint site and i want read in code global navigation information.
On properties page:
/_layouts/AreaNavigationSettings.aspx
I added "location","organization","98" nodes.
But when i am trying to get those nodes in code
using (var site = new Microsoft.SharePoint.SPSite(URL))
{
using (var currentWeb = site.OpenWeb())
{
return currentWeb.Navigation.GlobalNodes;
}
}
I have always those nodes:
Home
Quick launch
SharePoint Top Navbar
Why i have those strange nodes and how to get real globan naviigation/?
SharePoint's navigation is hierarchical. The hierarchy has exactly three nodes:
Home — represents the single 'home' icon in the upper left;
Quick launch — represents the quick launch menu at the left side of the page;
Top navigation bar — represents the navigation bar at the top of the page.
You have to delve into subnodes of these node to find your three nodes — see the SPNavigationNode.Children property. SharePoint lacks unique identifiers for navigation nodes so you have to rely on titles (display names).
UPDATE: Also please note that your code contains a serious design flaw. You are returning an object that's logically nested within a SPWeb out of the scope where the SPWeb instance is alive—i.e. out of the using statement. While this may work for navigation nodes generally such behavior will lead to errors. Those errors are often handled internally by SharePoint and result 'only' in logged error messages, but that's definitelly what your code should produce.
This works for me:
var pubWeb = PublishingWeb.GetPublishingWeb(web);
foreach (SPNavigationNode navigationNode in pubWeb.Navigation.GlobalNavigationNodes)
{
//do stuff
}

static/private child component in mxml?

Are there any way to declare a child component in mxml which is private/protected or even static?
Sure we can do this inside a script tag, but are there any other way?
Ashier suggests using the "Exclude" metadata tag, but Maskit offers its limitations and suggests alternative solutions:
http://blog.ashier.com/2008/03/25/hiding-properties-in-flex-components/
http://smaskit.blogspot.com/2008/07/making-mxml-subcomponent-private.html
In the strict meaning of these terms, no you can't do that using mxml. The second link posted by Luis contains some workarounds for private/protected behavior.
I found a solution to the static question. I wanted a quick memo pad that could be accessed anywhere in the mobile app, without one instance overwriting edits left open in a different screen.
I created a memo pad mxml control, and then placed it inside a declarations section in the top level application mxml. In each view that I wanted the memo to appear in, I added:
import mx.core.FlexGlobals;
import components.QuickMemo;
private var memo:QuickMemo;
In the view creation complete:
memo = FlexGlobals.topLevelApplication.memo;
In the viewActivation code, I added:
memo.visible = false;
addElement(memo);
In the viewDeactivation code, I included:
removeElement(memo);
The net effect is that only one instance of the memo exists at any time, and that one instance opens in whatever state it existed in the last view it appeared in.

Resources