Display Content based on situation (Xamarin.Forms) - xamarin.forms

I am creating an app using Xamarin Forms. I have a MainTab page that displays all the 4 tabs. There is one specific tab call Me tab.
As of now the Me Tab displays the user's profile. However, when the user is not logged in, it my UserLogin page should be displayed instead. How do I do that in Xamarin forms?

You can achieve this in various ways. If you're using a MVVM approach the most straight forward solution would be to set a binding in your viewmodel indicating user logging. Based on that you can set your
tabbedPage.CurrentPage = TheTabPageYouWant.
If you're using codebehind, just use in your ;
public bool UserLogged
{
get { return _userLogged; }
set
{
_userLogged = value;
if (_userLogged)
{
tabbedPage.CurrentPage = UserProfilePage.
return;
}
tabbedPage.CurrentPage = LogInPage.
}
I strongly recommend any Xamarin.Forms book and MVVM techniques for you.
Don't hesitate to ask any further questions.

Related

Prism navigation usage from Xamarin Forms App.OnAppLinkRequestReceived

I am building an app that makes use of some App links. In below example, I want to open a ResetPasswordPage when the user activates a link from an e-mail.
protected override async void OnInitialized()
{
InitializeComponent();
await NavigationService.NavigateAsync("/NavigationPage/LoginPage");
}
protected override void OnAppLinkRequestReceived(Uri uri)
{
if (uri.Host.EndsWith("site.nl", StringComparison.OrdinalIgnoreCase))
{
if (uri.AbsolutePath.StartsWith(#"/appname/resetpassword/"))
{
if (uri.Segments.Length == 4)
{
string resetCode = uri.Segments[3];
NavigationParameters param = new();
param.Add(NavConst.PasswordResetCode, resetCode);
await NavigationService.NavigateAsync("ResetPasswordPage", param);
}
}
}
}
This code works, but not what I would expect (for both iOS and Android). I would expect that ResetPasswordPage would be added to the navigation stack that was set in OnInitialized, so that it would contain a back button in the navigation bar, bringing the user back to the login page in this case.
But instead, it looks like the navigation stack gets replaced. When ResetPasswordPage is shown, and the user clicks the hardware back button, the app is closed. However, i want it to go back to where the user was before.
Am I not understanding some navigation concepts well or might this be a bug?
The NavigationService is a rather unique service within Prism for Xamarin.Forms. It is constructed new for each page as navigation and the navigation stack is dependent on where you are navigating from.
For instance when you Navigate from the context of a MasterDetailPage / FlyoutPage, it understands that you aren't trying to push a modal on top of that page but instead you are starting from the context of Detail/Flyout. If the NavigationService continually updated the Page context then the navigation service injected into that MasterDetailPage/FlyoutPage's ViewModel would have no idea that it needed that page as the context to navigate from.
Your issue here ultimately is that you are Navigating from the context of the Application which has a NavigationService with no Page set. As a result even a relative Navigation will still have the effect of an absolute Navigation thus resetting the Application.MainPage since that NavigationService does not have the contextual understanding of another page.
Depending on your business requirements you have a few different options. One is to do an absolute Navigation that gives you navigation stack that you're looking for.
Optionally you may want to get the currently displayed page and update the NavigationService to understand it. In the App class you might add something like:
protected override void OnAppLinkRequestReceived(Uri uri)
{
if (NavigationService is IPageAware pa)
{
page.Page = PageUtilities.GetCurrentPage(MainPage);
}
if (someCondition)
{
// This will now navigate from relatively from the page
// returned by GetCurrentPage.
NavigationService.NavigateAsync("SomeRelativeUrl")
.OnNavigationError(HandleNavigationError);
}
}

Xamarin.Forms: How to navigate to TabbedPage's child page

I meet a scenario to navigate from MyTabbedPage/ChildTabPage1/Page1 to MyTabbedPage/ChildTabPage2/Page2 in Xamarin.Forms
Right now, I can only switch between MyTabbedPage/ChildTabPage1 and MyTabbedPage/ChildTabPage2. But I need to navigate directly from MyTabbedPage/ChildTabPage1/Page1 to MyTabbedPage/ChildTabPage2/Page2
How to achieve this?
Thank you very much in advance for your helps.
You can try something like this.
public App()
{
InitializeComponent();
var parentPage = new MasterDetailView(); // name of the master detail page
parentPage.IsPresented = false;
var tabbedPage = new MasterDetailTabbedPage(); // name of the tabbed page
tabbedPage.CurrentPage = tabbedPage.Children[2]; // specify the index of the tab
parentPage.Detail = new NavigationPage(tabbedPage); // assign the tabbed page to master detail page
MainPage = parentPage; // navigate to master detail page (3rd tab selected)
}
If you want to navigate MyTabbedPage/ChildTabPage1/Page1 to MyTabbedPage/ChildTabPage2/Page2 in Xamarin.Forms, I suggest you can consider to use Shell to do this.
Xamarin.Forms Shell includes a URI-based navigation experience that uses routes to navigate to any page in the application, without having to follow a set navigation hierarchy. In addition, it also provides the ability to navigate backwards without having to visit all of the pages on the navigation stack.
Here is the article about using Shell:https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation

How can I disable the view of a page for other users?

I want that a user of my application to enable or disable the viewing of a certain page for other users. For that i need , somehow an application variable, a bool to be set true or false whether the user decides to enable or disable the view for other users.
The functionality that i want is : when i click on a button to disable the view for a page(for other users that are connected to site), and when i press back to enable it .
I can achieve this with the use of a database, by changing the value of a field in a table with true or false.But this approach is ineffective and not elegant.
Can someone tell me how I can achieve this without using databases ? Is there any application variable / session variable / or cookie to achieve this ? Is there something that i should write in Global.asax ?
I use ASP.NET MVC 4..
Please help!
In you Controller declare "static variable" say
static bool disableViewPage;
Set this value on click of button in the some action.
Example :
public class SomeViewController : Controller
{
[HttpPost]
public ActionResult DisableView(bool value)// on button click
{
SecondController.DisableViewPage=value;
return View("<SomeView>")
}
}
public class SecondController : Controller
{
public static bool DisableViewPage;
// your views
}

How to Show or hide controls based on roles - ASP.NET MVC 4 Razor

I m working on ASP.NET MVC 4 application.I have a dashboard and my users groups will be based on Windows Domain
So I am using WIndows Authentication for authenticating users.
I created sample applications which uses custom authentication by overrides functions AuthorizeAttribute, ActionFilterAttribute . Is this a good approach ?
Which attribute is best used for authentication ?
I have a dashboard. So I need to show or hide the controls based on roles.
Suppose if there is 3 grids(table), If Admin is logs in, he can able see 3 grids(tables).
But if Support user is log in he can see 2 grids (table) only.
My plan is to create partial views for each grid and so there will be an Action and Controller for each partial view.
There will be a database and in that I will specify the actions which each group can perform. So that I can filter the requests.
2 How can I hide or show the partial views based on roles ?.
I tried some SO links, but all they are talking about 2,3 roles and it was hard coded.
In my case roles may vary and we uses db to set up access for roles.
Thanks in advance.
You can use Following code for role based checking
#if(Request.IsAuthenticated)
{
if(User.IsInRole("Admin"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for Admin role</li>
</Ul>
}
if(User.IsInRole("User"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for User role</li>
</Ul>
}
}
#* For unknown user *#
else
{
<Ul Class="SubMenuItem">
<li> this menu item is for Unknown user</li>
</Ul>
}
Typically you would want to keep your views as clean as possible with little to no logic.
I would suggest moving your role checking logic into a controller action and rendering a partial view based on the users role.
You can use ChildActions and the Html.Action extension method to get this wired up.
From MSDN:
A child action method renders inline HTML markup for part of a view
instead of rendering a whole view. Any method that is marked with
ChildActionOnlyAttribute can be called only with the Action or
RenderAction HTML extension methods.
In your project, create a new Controller called Dashboard and added a single Action called BuildTable.
public class DashboardController : Controller
{
[ChildActionOnly]
public ActionResult BuildTable()
{
if (Roles.IsUserInRole("Administrator"))
{
return PartialView("_AdminTable");
}
return PartialView("_SupportTable");
}
}
Include the following line in the view where you want the dashboard table to appear.
#Html.Action("BuildTable", "Dashboard")
I have done something similar. The way I did it (may not be the best)
is to send a boolean back to the view
in the controller use:
bool showSection1 = true;
bool showSection2 = false;
ViewData["showSection1"] = showSection1;
ViewData["showSection2"] = showSection2;
/// may be better to use a viewmodel here rather than ViewData
then in the view:
#if((bool)ViewData["showSection1"])
{
#{Html.RenderPartial("section1");}
}
#if((bool)ViewData["showSection2"))
{
#{Html.RenderPartial("Section2");}
}
you will need to do the logic to set the boolean the way you want them but this should be a start.
you could also create a static method that returns the role and then get that value directly from the view. this may be bad form though.
#if(AppHelper.GetRole().equals("role1")){
//show the partial
}
then create a class called AppHelper and a method called GetRole that returns the role of the user.

Handling complex navigation in Flex

I am building a complex Flex app, and now I am at the point where navigation becomes a problem. I make use of Viewstacks with a Menu Bar, but I am not sure how to clearly structure this.
Depending on the logged in User and chosen Company by the user, he can see different pages. For now I restricted this hiding the appropriate buttons in the Menu Bar. However, not just the menu bar, but also buttons/links from within the app should be able to navigate to each existing page.
When I am loading up an existing page, it needs some initialization (depending on the context it is loaded from). In addition, when a company is chosen, I need to load the status from the backend, and depending on this status a specific page might be visible.
Are there any guidelines how to tackle more complex navigation/site hierarchies in Flex?
Now I am having all my views in a viewstack in the Application, and refer to it with Application.application.appViews.selectedChild -> but that's obviously not best practice, since it violates encapsulation.
Was thinking of implementing some sort of State Machine, which takes care of all this, but not quite sure it this would make sense, or if there is any better way.
Thanks guys,
Martin
If it's really complex, you might want to consider breaking your application up into modules.
Also, Mate is a great Flex framework for handling complex communication and navigation. Mate's EventMaps help you centralize the communication and logic between components, modules, etc. And, it keeps you away from the dreaded Application.application references.
Even if you don't use a framework like Mate, you can avoid the Application.application references by having components dispatch custom events that bubble up to the top-level of your application. The top level of the application can listen and catch these events and act on them. I've found this to be a much more flexible approach. I avoid Application.application as much as possible!
If you have a complex menu bar that needs to enable / disable a lot of buttons or options based on many different logic conditions, the State pattern is a decent way to handle it. I built an enterprise-level app that had a "Word-like" button bar at the top...and there were so many different conditions that affected the states of the buttons that I had to centralize the logic in one place. At first I didn't use the State pattern and maintaining the code was a difficult chore. One day, I bit the bullet and re-factored all the conditional logic into a StateManager class. It definitely made life easier from there on out.
Again, you might want to consider using Custom Events to broadcast important events to your application. You can make these events bubble up to the Application level. Then, by adding event listeners at the Application level, you can capture and respond to these events and target components or modules from the Application level. This gives you a central location for handling events and "directing traffic". It also prevents the tight-coupling of the Application.application approach. (Which quickly becomes a nightmare as your application grows and scales!)
For example, your StateManager can contain the case statements for deciding which state your application needs to be in. Once the decision about the current state is determined, you would dispatch a custom StateEvent. (Which might have properties like StateEvent.STATE_CHANGED and StateEvent.CURRRENT_STATE) This event can bubble up to the Application level and be caught by a listener. The listener then calls a method to load / change the state.
Does that clarify it for you? If not, perhaps I can spend an hour or two putting together a little sample.
Let me know,
=Bryan=
I can give you the approach I used for some of your sub-questions, the problem of initializing a page at runtime and how to encapsulate navigation.
For page initialization, the issue I came across is that it's not always known once you navigate to a page whether certain elements should be shown, since it not-only depends on overall user permissions, but also permissions against the currently-selected data. And if the information needed to determine this must be loaded from the server, you cannot show the page as-is while loading the information. So we created a control called LoadingPanel, which is a container that can cover content with a loading indicator until additional information has been received. Here's a shortened version of the ActionScript:
[DefaultProperty("children")]
public class LoadingPanel extends ViewStack
{
public function LoadingPanel()
{
this.resizeToContent = false;
super();
}
public function get children():Array { return _children }
public function set children(value:Array):void { _children = value; }
public function get loadingImageStyle():String {
return _loadingImgStyle; }
public function set loadingImageStyle(value:String):void {
_loadingImgStyle = value;
if (_loadingIndic)
_loadingIndic.loadingImageStyle = value;
}
public function showLoadingIndicator():void
{
if (_loadingIndic)
{
super.selectedChild = _loadingIndic;
}
else
{
_pendingLoadingIndic = true;
var me:LoadingPanel = this;
var listener:Function = function(event:Event):void
{
if (me._pendingLoadingIndic)
me.showLoadingIndicator();
}
addEventListener(FlexEvent.CREATION_COMPLETE, listener);
}
}
public function hideLoadingIndicator():void
{
_pendingLoadingIndic = false;
if (_content)
{
super.selectedChild = _content;
}
else
{
var me:LoadingPanel = this;
var listener:Function = function(event:Event):void
{
me.hideLoadingIndicator();
}
addEventListener(FlexEvent.CREATION_COMPLETE, listener);
}
}
public function waitForEvent(target:EventDispatcher, event:String):void
{
_eventCount++;
showLoadingIndicator();
var me:LoadingPanel = this;
target.addEventListener(
event,
function(evt:Event):void
{
me._eventCount--;
if (!me._eventCount)
{
me.hideLoadingIndicator();
}
}
);
}
override public function addChild(child:DisplayObject):DisplayObject
{
var result:DisplayObject = child;
if (_content)
{
result = _content.addChild(child);
invalidateDisplayList();
}
else
{
if (!_children)
{
_children = [];
}
_children.push(child);
}
return result;
}
override protected function createChildren():void
{
super.createChildren();
if (!_content)
{
_content = new Box();
_content.percentWidth = 1.0;
_content.percentHeight = 1.0;
super.addChild(_content);
}
if (!_loadingIndic)
{
_loadingIndic = new LoadingIndicator();
_loadingIndic.percentWidth = 1.0;
_loadingIndic.percentHeight = 1.0;
_loadingIndic.loadingImageStyle = _loadingImgStyle;
super.addChild(_loadingIndic);
}
if (_children)
{
for each (var child:DisplayObject in _children)
{
_content.addChild(child);
}
}
}
private var _loadingImgStyle:String = "loadingIndicatorDark";
private var _loadingIndic:LoadingIndicator = null;
private var _content:Box = null;
private var _children:Array = null;
private var _pendingLoadingIndic:Boolean = false;
private var _eventCount:int = 0;
}
We typically used these by wrapping a LoadingPanel around content then calling the panel's waitForEvent method. Typically, the event we'd wait for is for a web service response to come in. The class also lets you wait on multiple events before it will show its children.
Another recommendation I would make for your project is that you look into deep linking in Flex. Our users appreciated being able to bookmark a resource/location in our complex Flex application as well as being able to hit refresh in their browser and return to the same "page" they were on. But implementing deep linking also helped me out for one of the problems you mentioned; how do you send the UI to a specific page in an encapsulated manner? The way we did it is by raising a bubbling navigation event containing a destination "URL." A top-level navigation "manager" then handled interpreting the URL and "sending" the user to the appropriate area.
Hopefully this will give you some ideas for some of the challenges you face.

Resources