I am currently learning Xamarin development, looks like quite a big learning curve.
Well I have a tabbed page class (TabbedPageTest.cs) which I inherited from TabbedPage.
Now how can I just view that page.
Let's say I wanted to navigate using a cell from a table view.
TableView tb = new TableView
{
Intent = TableIntent.Menu,
Root = new TableRoot
{
new TableSection("Tabbed Page Test")
{
new TextCell
{
// What all codes can I add here to navigate or view TabbedPageTest.cs?
}
}
}
}
//Tabbed Page Demo Code to be used in PCL for Xamarin.Forms
TabbedPage tabs = new TabbedPage ();
tabs.Children.Add(
new NavigationPage (new MainPage () { Title = "Title for MainPage" }) {
Title = "Tile for TabbedPage Tab1" // Add this title for your TabbedPage
}
);
tabs.Children.Add(
new NavigationPage (new FirstPage () { Title = "Title for FirstPage" }) {
Title = "Tile for TabbedPage Tab2" // Add this title for your TabbedPage
}
);
return tabs;
Hope this helps
Here is my code for a tabbed page in Xamarin Forms...
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:me="clr-namespace:EvalUate;assembly=EvalUate"
x:Class="EvalUate.MainPage"
Title="EvalUate">
<TabbedPage.Children>
<me:AppliancePage />
<me:HelpPage />
<me:LicensePage />
</TabbedPage.Children>
</TabbedPage>
With that in place, no code is needed, it will find the correct page.
You asked for the code in C#. Here you go...
public partial class MainPage : TabbedPage // Note inherits from TabbedPage
{
public MainPage ( )
{
this.Title = "Tabbed Page Demo";
var appliancePage = new AppliancePage ( );
var helpPage = new HelpPage ( );
this.Children.Add( appliancePage );
this.Children.Add( helpPage );
}
}
The above is in MainPage.cs. MainPage.xaml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" <!-- note TabbedPage -->
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlToCSharpDemo.MainPage">
</TabbedPage>
Remember that each child page (e.g., HelpPage) must have a title...
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlToCSharpDemo.HelpPage" Title="Help"> <!-- Note Title -->
<ContentPage.Content>
<Label Text="Help Page"/>
</ContentPage.Content>
</ContentPage>
Related
I want to display a small popup in a xamarin forms application (iOS/Android PCL)
I am actually working with a ContentPage (XAML + C# code)
and i am showing this popup with:
await Navigation.PushModalAsync(mypopupinstance)
It works fine, but the popup is on the full screen. I just want a small popup and i want to see what is behind.
Thanks
You'll need to look elsewhere for this kind of functionality. One such library is Rotorgames' Popup plugin: https://github.com/rotorgames/Rg.Plugins.Popup
Modal pages can't be presented like that.
For small popups you can use
DisplayAlert()
Inside a Page.
If you want something more customizable just wrap the content of your Page Inside a relative Layout or grid, and add the popup on top of your normal content.
I am working on the same issue, so far I was able to create a popup which can hold a content page.
I am gladly willing to share my current state. Please note that I will keep the code examples as short as possible, therefore reducing it to a simple loading and a text prompt dialog.
Approach
After having used the Acr.UserDialogs library for a while, i felt the need of having dialogs I could customize due to my personal requirements. Also I wanted to minimize the necessity of having to rely on plugins.
Ideally such a dialog should be invoked with a simple call, for instance:
Dialogs.ShowLoading();
or
string result = Dialogs.ShowPrompt();
As things are with Xamarin.Forms it is quite obvious that we will require a dependency service implementation for that to work.
Shared Code Library
We create a basic interface "IDialogs.cs":
public interface IDialogs
{
bool IsDialogOpen();
void ShowLoading(LoadingDialog dialog);
void ShowPrompt(PromptDialog dialog);
void HideDialog();
}
Next thing to do is to have a static dialog class, which can be called from every page where a dialog is needed.
"Dialogs.cs":
public static class Dialogs
{
private static IDialogs dialogService = DependencyService.Get<IDialogs>();
public static bool IsDialogOpen()
{
return dialogService.IsDialogOpen();
}
public static void ShowLoading()
{
LoadingDialog dlg = new LoadingDialog();
dialogService.ShowLoading(dlg);
}
public static Task<string> ShowPromptText()
{
TaskCompletionSource<string> dialogCompletion = new TaskCompletionSource<string>();
PromptDialog dialog = new PromptDialog();
dialog.Canceled += (object sender, object result) => { dialogService.HideDialog(); dialogCompletion.SetResult((string)result); };
dialog.Confirmed += (object sender, object result) => { dialogService.HideDialog(); dialogCompletion.SetResult((string)result); };
dialogService.ShowPrompt(dialog);
return dialogCompletion.Task;
}
public static void HideDialog()
{
dialogService.HideDialog();
}
}
You will notice, that we are using a TaskCompletionSource together with custom event handlers in the ShowPromptText method. This enables us to display the dialog and await the user pressing the okay or cancel button and consuming the returned result.
As of now, the dialogs are as simple as they can get. I use some additional code for styling and themeing, but i will leave that out in order to keep this answer short and simple.
The loading dialog:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Dialogs.LoadingDialog" BackgroundColor="Transparent">
<ContentPage.Content>
<Grid BackgroundColor="#bb000000">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Frame BackgroundColor="Black" CornerRadius="15" Grid.Row="1" x:Name="ContentGrid" Margin="100,0,100,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ActivityIndicator Grid.Row="0" Color="White" IsRunning="True" HorizontalOptions="Center" VerticalOptions="Center"/>
<Label x:Name="LoadingLabel" Text="Loading ..." VerticalOptions="End" HorizontalOptions="Center" Grid.Row="1" TextColor="White" />
</Grid>
</Frame>
</Grid>
</ContentPage.Content>
(no need to post xaml.cs code for this, since there is no interaction with a loading screen)
The prompt dialog
PromptDialog.Xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:dialogs="clr-namespace:BetterUI.Dialogs"
x:Class="MyApp.Dialogs.PromptDialog" BackgroundColor="Transparent">
<ContentPage.Content>
<ScrollView>
<Grid BackgroundColor="#bb000000">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Frame x:Name="ContentGrid" Grid.Row="1" CornerRadius="15" BackgroundColor="White" Margin="50,0,50,0" Padding="0">
<Grid Grid.Row="1" Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid x:Name="HeadingGrid" Padding="10, 5, 10, 5" Margin="-15,0,-15,0" Grid.Row="0" BackgroundColor="Black">
<Label x:Name="HeadingLabel" Text="Enter text" TextColor="White" Margin="20,0,20,0"/>
</Grid>
<Label l x:Name="DescriptionLabel" Text="Enter your text" Grid.Row="1" Margin="15,0,15,0"/>
<Entry x:Name="DialogResultText" Placeholder="Text" PlaceholderColor="LightGray" TextColor="Black" Grid.Row="2" Margin="15,0,15,0"/>
<Grid Grid.Row="3" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="CancelButton" Text="Cancel" Clicked="OnCancelClick" Grid.Column="0" CornerRadius="0"/>
<Button x:Name="ConfirmButton" Text="Okay" Clicked="OnOkayClick" Grid.Column="1" CornerRadius="0"/>
</Grid>
</Grid>
</Frame>
</Grid>
</ScrollView>
</ContentPage.Content>
PromptDialog.xaml.cs:
public partial class PromptDialog : ContentPage
{
public event EventHandler<object> Confirmed;
public event EventHandler<object> Canceled;
public PromptDialog()
{
InitializeComponent();
}
private void OnCancelClick(object sender, EventArgs e)
{
Canceled?.Invoke(this, string.Empty);
}
private void OnOkayClick(object sender, EventArgs e)
{
Confirmed?.Invoke(this, DialogResultText.Text);
}
}
Android implementation
First of all we will create the android implementation of our IDialogs interface created in the shared code earlier:
[assembly: Dependency(typeof(DialogService))]
namespace MyApp.Droid.Services
{
/// <summary>
/// Handles displaying dialog items on screen
/// </summary>
public class DialogService : IDialogs
{
private static DialogFragment currentDialog;
/// <summary>
/// returns if a dialog is already open
/// </summary>
/// <returns></returns>
public bool IsDialogOpen()
{
return (currentDialog != null && currentDialog.IsVisible);
}
/// <summary>
/// Initialize Dialog Service with activity
/// </summary>
/// <param name="activity">activity</param>
public static void Init(Activity activity)
{
Activity = activity;
}
public static Activity Activity { get; set; }
/// <summary>
/// Displays a loading dialog
/// </summary>
/// <param name="dialog">Instance of progress dialog (xamarin.forms)</param>
public void ShowLoading(Dialogs.LoadingDialog dialog)
{
if (Activity == null)
return;
DialogFragment frag = dialog.CreateDialogFragment(Activity);
frag.SetStyle(DialogFragmentStyle.NoTitle, Resource.Style.DialogFrame);
frag.Show(Activity.FragmentManager, "dialog");
currentDialog = frag;
}
/// <summary>
/// Displays a prompt dialog
/// </summary>
/// <param name="dialog"></param>
public void ShowPrompt(Dialogs.PromptDialog dialog)
{
if (Activity == null)
return;
DialogFragment frag = dialog.CreateDialogFragment(Activity);
frag.SetStyle(DialogFragmentStyle.NoTitle, Resource.Style.DialogFrame);
frag.Show(Activity.FragmentManager, "dialog");
currentDialog = frag;
}
/// <summary>
/// Hides loading dialog
/// </summary>
public void HideDialog()
{
if (Activity == null)
return;
if (currentDialog != null)
{
currentDialog.Dismiss();
currentDialog = null;
}
}
}
}
Note that you have to set the activity for the dialog service prior to calling the actual methods to show a dialog, so in your MainActivity.cs make sure to call
DialogService.Init(this);
after having initialized Xamarin.Forms.
Finally, here comes some black magic:
Usually, one would implement such a dialog in Android by putting a fragment container into the main layout and throwing a fragment inside. Unfortunately, due to using Xamarin.Forms, such a main layout isn't available by default.
Even though Xamarin.Forms offers a view extension, which allows converting a ContentPage to a fragment (ContentPage.CreateFragment), we won't have any success of using this because it needs a target fragment container to be placed in.
However, android provides something called a DialogFragment, which can be thrown at the screen without having the need of a defined fragment container.
Unfortunately there isn't any out-of-the-box solution for creating a DialogFragment from Xamarin Forms. Good news is that this can be overcome with the power of using System.Reflection(;), so we create our own extension method and some modified versions of internal classes, xamarin.forms uses under the hood. In order to achieve this, I took the code from Xamarin.Forms in Xamarin.Platform.Android and modified it to create a DialogFragment from a ContentPage:
public static class PageExtensions
{
public static DialogFragment CreateDialogFragment(this ContentPage view, Context context)
{
if (!Forms.IsInitialized)
throw new InvalidOperationException("call Forms.Init() before this");
// Get Platform constructor via reflection and call it to create new platform object
Platform platform = (Platform)typeof(Platform).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(Context), typeof(bool) }, null)
?.Invoke(new object[] { context, true });
// Set the page to the platform
if (platform != null)
{
platform.GetType().GetMethod("SetPage", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(platform, new object[] { view });
// Finally get the view group
ViewGroup vg = (Android.Views.ViewGroup)platform.GetType().GetMethod("GetViewGroup", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(platform, null);
return new EmbeddedDialogFragment(vg, platform);
}
return null;
}
public class DefaultApplication : Xamarin.Forms.Application
{
}
class EmbeddedDialogFragment : DialogFragment
{
readonly ViewGroup _content;
readonly Platform _platform;
bool _disposed;
public EmbeddedDialogFragment()
{
}
public EmbeddedDialogFragment(ViewGroup content, Platform platform)
{
_content = content;
_platform = platform;
}
public override global::Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
this.Dialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
return _content;
}
public override void OnDestroy()
{
this.Dialog?.Window.SetSoftInputMode(SoftInput.AdjustPan);
base.OnDestroy();
}
protected override void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
if (disposing)
{
(_platform as IDisposable)?.Dispose();
}
base.Dispose(disposing);
}
}
}
iOS implementation
Fortunately, for the iOS implementation no deep diving into Xamarin.Forms code is necessary:
Here is the iOS implementation of DialogService:
[assembly: Dependency(typeof(DialogService))]
namespace BetterUI.iOS.Services
{
public class DialogService : IDialogs
{
private UIViewController currentDialog;
private UIWindow popupWindow = null;
public void HideLoading()
{
if (currentDialog != null)
{
UIApplication.SharedApplication.KeyWindow.RootViewController.DismissModalViewController(false);
currentDialog.Dispose();
currentDialog = null;
}
}
public bool IsDialogOpen()
{
return (currentDialog != null && currentDialog.IsBeingPresented);
}
public void ShowLoading(LoadingDialog dialog)
{
UIViewController dialogController = dialog.CreateViewController();
ShowDialog(dialogController);
currentDialog = dialogController;
}
public void ShowPrompt(PromptDialog dialog)
{
UIViewController dialogController = dialog.CreateViewController();
ShowDialog(dialogController);
currentDialog = dialogController;
}
private void ShowDialog(UIViewController dialogController)
{
var bounds = UIScreen.MainScreen.Bounds;
dialogController.View.Frame = bounds;
UIApplication.SharedApplication.KeyWindow.RootViewController.ModalPresentationStyle = UIModalPresentationStyle.CurrentContext;
UIApplication.SharedApplication.KeyWindow.RootViewController.AddChildViewController(dialogController);
UIApplication.SharedApplication.KeyWindow.RootViewController.View.Opaque = false;
UIApplication.SharedApplication.KeyWindow.RootViewController.View.Layer.AllowsGroupOpacity = true;
UIApplication.SharedApplication.KeyWindow.RootViewController.View.Layer.BackgroundColor = new CGColor(Color.White.ToCGColor(), 0.0f);
UIApplication.SharedApplication.KeyWindow.RootViewController.View.BackgroundColor = UIColor.Clear;
UIApplication.SharedApplication.KeyWindow.RootViewController.View.AddSubview(dialogController.View);
dialogController.ModalPresentationStyle = UIModalPresentationStyle.OverCurrentContext;
dialogController.View.Opaque = false;
dialogController.View.BackgroundColor = UIColor.Clear.ColorWithAlpha(0.0f);
}
}
}
Et voila, now whenever we use the calls from the "Approach"-Section of this post, a nice popup dialog containing our custom Xamarin.Forms ContentPage will show up.
It is easier to use a package, like Plugins.Popup to achieve this, without custom renderers, it is impossible to add an Image to the default AlertDialog, which will limit you.
Using Popup Plugin, you just have to add it to your solution, initialize in both iOS and Android:
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Rg.Plugins.Popup.Popup.Init();
global::Xamarin.Forms.Forms.Init ();
LoadApplication (new App ());
return base.FinishedLaunching (app, options);
}
}
Android:
namespace HelloXamarinFormsWorld.Android
{
[Activity(Label = "HelloXamarinFormsWorld", MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Rg.Plugins.Popup.Popup.Init(this, bundle);
Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication (new App ());
}
}
}
Create a Popup Page
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="True"/>
</pages:PopupPage.Animation>
<!--You can use any elements here which are extended from Xamarin.Forms.View-->
<StackLayout
VerticalOptions="Center"
HorizontalOptions="Center"
Padding="20, 20, 20, 20">
<Label
Text="Test"/>
</StackLayout>
And, to show in your page:
await Navigation.PushPopupAsync(page);
As of March 22, 2022, there is a Popup Included in the Xamarin Community Toolkit. You can find Microsoft's documentation here.
An object instantiation through XAML:
<xct:Popup xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="clr-namespace:Xamarin.CommunityToolkit.UI.Views;assembly=Xamarin.CommunityToolkit"
x:Class="MyProject.SimplePopup">
<StackLayout>
<Label Text="Hello Simple Popup" />
</StackLayout>
</xct:Popup>
An object instantiation through code:
using Xamarin.CommunityToolkit.UI.Views;
// can also specify a type to be returned from the dismissal of the popup
// e.g. var popup = new Popup<string>
var popup = new Popup
{
// Can set the content to any custom layout
Content = new StackLayout
{
Children =
{
new Label
{
Text = "Hello Simple Popup"
}
}
}
};
You can show the popup through the Navigation stack:
using Xamarin.CommunityToolkit.Extensions;
App.Current.MainPage.Navigation.ShowPopup(popup);
Or call it through await App.Current.MainPage.Navigation.ShowPopupAsync(popup);
It also has events you can intercept and handle, like popup.Dismissed.
The popup can even return a value when it is dismissed if you instantiate it with a type specified:
// provide the <T> type string here for the example
var popup = new Popup<string>
{
Content = new StackLayout
{
Children =
{
new Label
{
Text = "Hello Simple Popup"
},
new Button
{
Text = "Dismiss",
// pass the <T> you would like as the result into Dismiss
// in this case it is a string "Dismiss was clicked"
Command = new Command(() => Dismiss("Dismiss was clicked"))
}
}
}
};
var result = await App.Current.MainPage.Navigation.ShowPopupAsync(popup);
Console.WriteLine(result);
Use package named 'Rg.Plugin.Popup'. It will help you.
Hello I am new to Xamarin Development and I am currently working on PCL project.
I did implementation of the Navigation drawer using MasterDetailsPage concept. It is working fine.
But issue I am facing is that MasterDetailsPage is coming with the Blue Color Actionbar and menu icon to open/close navigation drawer.I need to override it with black color. Kindly suggest something.
I have mentioned the code I am currently using.
Also, there is whitespace appearing, I want get rid of it.
On below URl they have mentioned some ways, as I am new to this not able to write the CustomRenderer for each platform.
https://forums.xamarin.com/discussion/comment/244966/#Comment_244966
Please giude me how to write a customrenderer to remove that white space as well as change color of toolbar.
Code:
My XAML File :
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:WYH_XAMARIN.MasterDetailPageNavigation"
x:Class="WYH_XAMARIN.MasterDetailPageNavigation.NavigationDrawerPage">
<MasterDetailPage.Master>
<ContentPage Title="Menu"
BackgroundColor="#e8e8e8">
<StackLayout Orientation="Vertical">
<!--
This StackLayout you can use for other
data that you want to have in your menu drawer
-->
<StackLayout BackgroundColor="#e74c3c"
HeightRequest="75">
<Label Text="Some Text title"
FontSize="20"
VerticalOptions="CenterAndExpand"
TextColor="White"
HorizontalOptions="Center"/>
</StackLayout>
<ListView x:Name="navigationDrawerList"
RowHeight="60"
SeparatorVisibility="None"
BackgroundColor="#e8e8e8"
ItemSelected="OnMenuItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!-- Main design for our menu items -->
<StackLayout VerticalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="20,10,0,10"
Spacing="20">
<Image Source="{Binding Icon}"
WidthRequest="40"
HeightRequest="40"
VerticalOptions="Center" />
<Label Text="{Binding Title}"
FontSize="Medium"
VerticalOptions="Center"
TextColor="Black"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
and my class file is :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WYH_XAMARIN.PojoClasses;
using Xamarin.Forms;
namespace WYH_XAMARIN.MasterDetailPageNavigation
{
public partial class NavigationDrawerPage : MasterDetailPage
{
LoginSuccessfullResponse loginSuccessResponse;
public List<MasterPageItem> menuList { get; set; }
public NavigationDrawerPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
menuList = new List<MasterPageItem>();
// Creating our pages for menu navigation
// Here you can define title for item,
// icon on the left side, and page that you want to open after selection
var page1 = new MasterPageItem() { Title = "My Profile", Icon = "icon.png", TargetType = typeof(TestPage1) };
var page2 = new MasterPageItem() { Title = "Service Booking", Icon = "icon.png", TargetType = typeof(TestPage2) };
var page3 = new MasterPageItem() { Title = "Item 3", Icon = "icon.png", TargetType = typeof(TestPage3) };
// Adding menu items to menuList
menuList.Add(page1);
menuList.Add(page2);
menuList.Add(page3);
// Setting our list to be ItemSource for ListView in MainPage.xaml
navigationDrawerList.ItemsSource = menuList;
// Initial navigation, this can be used for our home page
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(TestPage1)));
}
public NavigationDrawerPage(LoginSuccessfullResponse loginSuccessResponse)
{
this.loginSuccessResponse = loginSuccessResponse;
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
menuList = new List<MasterPageItem>();
// Creating our pages for menu navigation
// Here you can define title for item,
// icon on the left side, and page that you want to open after selection
var page1 = new MasterPageItem() { Title = "My Profile", Icon = "icon.png", TargetType = typeof(TestPage1) };
var page2 = new MasterPageItem() { Title = "Service Booking", Icon = "icon.png", TargetType = typeof(TestPage2) };
var page3 = new MasterPageItem() { Title = "Item 3", Icon = "icon.png", TargetType = typeof(TestPage3) };
// Adding menu items to menuList
menuList.Add(page1);
menuList.Add(page2);
menuList.Add(page3);
// Setting our list to be ItemSource for ListView in MainPage.xaml
navigationDrawerList.ItemsSource = menuList;
// Initial navigation, this can be used for our home page
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(TestPage1)));
}
// Event for Menu Item selection, here we are going to handle navigation based
// on user selection in menu ListView
private void OnMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (MasterPageItem)e.SelectedItem;
Type page = item.TargetType;
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsPresented = false;
}
}
}
Guys please help me to resolve this.
Any sample code or working tutorial will be helpful.
Thanks in advance!!
But issue I am facing is that MasterDetailsPage is coming with the Blue Color Actionbar and menu icon to open/close navigation drawer.
You do not need to do customer render to change the ActionBar color
try to use
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(MainPage))) { BarBackgroundColor = Color.Red };
there is whitespace appearing
I did not reproduce your issue, my master detail page works fine without write line. You can refer to my project.
by checking the answer of the link you provide. I have created a customer render of MarstDetialPage at android project:
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(CustomMasterDetailRenderer))]
namespace MasterDetialPage_MyTest.Droid
{
public class CustomMasterDetailRenderer : MasterDetailPageRenderer
{
public override void AddView(Android.Views.View child)
{
child.GetType().GetRuntimeProperty("TopPadding").SetValue(child, 0);
var padding = child.GetType().GetRuntimeProperty("TopPadding").GetValue(child);
base.AddView(child);
}
}
}
It will get screen without notification bar.
Note: I have only test it on the android platform
I have created a controller with following code.
**I am not using any model in this example.
public ActionResult PersonalDetails()
{
return View();
}
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
return View();
}
also a view is added for PersonalDetails action with following markup.
#{
ViewBag.Title = "PersonalDetails";
}
<h2>PersonalDetails</h2>
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>PersonalDetails</h2>
#using (Html.BeginForm("Thanks", "DemoForms", FormMethod.Post))
{
#Html.ValidationSummary()
<p>
Your Name : #Html.TextBox("FirstName")
</p>
<br />
<p>
Your Name : #Html.TextBox("LastName")
</p>
<p> Your Phone : #Html.TextBox("Phone")</p>
<p> #Html.RadioButton("Gender", "Male", true) Male</p>
<br />
<p>#Html.RadioButton("Gender", "Female", false) Female </p>
<p> #Html.CheckBox("Reading", true) Reading</p><br />
<p> #Html.CheckBox("Cooking", false) Cooking</p><br />
<p> #Html.CheckBox("Cooking", false) Painting</p><br />
<p>
Would you like to participate in Survey?
#Html.DropDownList("ddlResponse", new[]
{
new SelectListItem() {Text="Yes", Value="Yes"},
new SelectListItem() {Text="No", Value="No"}
}, "Choose an Option")
</p>
<input type="submit" value="Submit Invite" />
}
when user enter the information in above view and click on submit button, it will redirect to Thanks action.
I want to create a Thanks view that will show this information.
Please let me know how I can show/ access the information on Thanks view.
Thank you in advance.
A typical way to do this is to simply send the data to the new view on the server. There are a lot of different patterns. For model binding, do something like this:
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
ThanksViewModel model=new ThanksViewModel();
//add the data to the model
return View(model); //return the model with the view
}
If you're not using the model-binding functionality in your view pages, you can always pass data using the ViewBag:
[HttpPost]
public ActionResult Thanks(FormCollection formcol)
{
ViewBag.ThanksData="data"; //add data as properties of ViewBag
return View();
}
The ViewBag is just a built-in dynamic type that you can store any data on. You can then render this data in the view using the standard razor syntax. Eg in the razor page:
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>PersonalDetails</h2>
<p>#ViewBag.ThanksData</p>
We can use TempData also
In Controller:
[HttpPost]
public ActionResult Thanks()
{
TempData["Thanksdata"] = "data";
return View();
}
In View:
<h2>#TempData["Thanksdata"]</h2>
we can use Viewdata also
in controller:
ViewData["Thanksdata"] = "data";
View:
<h2>#ViewData["Thanksdata"]</h2>
Difference between ViewData ViewBag TempData
http://www.c-sharpcorner.com/Blogs/14947/difference-between-viewdata-viewbag-and-tempdata.aspx
Can anyone give out the best practices for playing around with controls at runtime such as creating a new view,adding views inside a view,adding controls to containers using MVVM pattern without breaking mvvm pattern??
I am using MVVMlight toolkit..
please help me out in this regard..
Thanks in advance......
This post discusses the strategies for creating views (dialogs) from your view models.
Edit:
From your comment I take it that you got an user interface that has an add and delete button. The add button should add an item (type ?) to a ItemsControl ... hope that's correct.
So, how would I do this, well I would create a view model that has an ObservableCollecion<ItemViewModel>. The ItemViewModle is the view mode that represents the item that should be added to the ItemsControl (so in your case the view model backing your "rangeView").
Then I would add two commands that handle the addition and deletion of items. Both commands just add/remove ItemViewModels from your collection.
To show the items in the view I would bind the ItemControl.ItemsSource property to the collection in your main view model (i.e. the one holding the ItemViewModel instances). The I would supply an ItemTemplate to render the items on the screen.
Ok, here is an example of what I think you are trying to do (at least conceptionally). Complete Source Code here. In the example I used a ListBox as it allows me easily to determine which item is selected, this depends on your szenario. Also note that you have complete freedom to customize the Template, the ItemPanelTemplate, and DataTemplate to fit your needs. You can even use this approacht to create PanoramaPages in WP7!
2nd edit: ItemsControl does not have a SelectedItem property. To get to it you have to use a control inheriting from Selector (e.g. a ListBox as I did) or you can use the Selector directly.
ItemViewModel:
public class ItemViewModel : ViewModelBase
{
#region [Name]
public const string NamePropertyName = "Name";
private string _name = null;
public string Name {
get {
return _name;
}
set {
if (_name == value) {
return;
}
var oldValue = _name;
_name = value;
RaisePropertyChanged(NamePropertyName);
}
}
#endregion
}
MainViewModel:
public class MainViewModel : ViewModelBase
{
public MainViewModel() {
if (IsInDesignMode) {
this.Items = new ObservableCollection<ItemViewModel>(Enumerable.Range(0, 10).Select((x, i) => new ItemViewModel() { Name = "Design Time Item " + i }));
} else {
// Code runs "for real"
}
}
#region [AddCommand]
private RelayCommand _addCommand;
public RelayCommand AddCommand {
get {
return _addCommand ?? (_addCommand = new RelayCommand(
() => {
this.Items.Add(new ItemViewModel() { Name = "New item - " + DateTime.Now });
}
));
}
}
#endregion
#region [DeleteCommand]
private RelayCommand _deleteCommand;
public RelayCommand DeleteCommand {
get {
return _deleteCommand ?? (_deleteCommand = new RelayCommand(
() => {
this.Items.Remove(this.SelectedItem);
},
() => { return this.SelectedItem != null; }
));
}
}
#endregion
#region [Items]
public const string ItemsPropertyName = "Items";
private ObservableCollection<ItemViewModel> _items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items {
get {
return _items;
}
set {
if (_items == value) {
return;
}
var oldValue = _items;
_items = value;
RaisePropertyChanged(ItemsPropertyName);
}
}
#endregion
#region [SelectedItem]
public const string SelectedItemPropertyName = "SelectedItem";
private ItemViewModel _selectedItem = null;
public ItemViewModel SelectedItem {
get {
return _selectedItem;
}
set {
if (_selectedItem == value) {
return;
}
var oldValue = _selectedItem;
_selectedItem = value;
RaisePropertyChanged(SelectedItemPropertyName);
// important in SL to notify command that can execute has changed !
this.DeleteCommand.RaiseCanExecuteChanged();
}
}
#endregion
}
MainPage.xaml
<UserControl
x:Class="MvvmLight1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Height="300"
Width="300"
DataContext="{Binding Main, Source={StaticResource Locator}}"
>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<!-- we are dealing with ItemViewModels now -->
<Border BorderThickness="0,0,0,1" BorderBrush="Gray" Padding="10,5">
<TextBlock Text="{Binding Name}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Margin="5,10" Content="Add" Command="{Binding AddCommand}" Width="70"/>
<Button Margin="5,10" Content="Delete" Command="{Binding DeleteCommand}" Width="70"/>
</StackPanel>
</Grid>
</UserControl>
I am trying to add a new IFrame portlet in liferay on click of a link. I have achieved it with some issues.
First I created a portlet using liferay sdk and customized the default view.jsp:
<portlet:renderURL var="pageDisp">
<portlet:param name="jspPage" value="/view.jsp" />
</portlet:renderURL>
Google <br />
Yahoo <br />
Daily Tech <br />
Wired <br />
Changed portlet.xml from
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
to
<portlet-class>test.LinksPortlet</portlet-class>
I have implemented the following code in LinksPortlet:
public void render(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
log("LinksPortlet:render");
try {
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
LayoutTypePortlet layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
List<Portlet> portletList = layoutTypePortlet.getPortlets();
for(Portlet p : portletList) {
log(p.getPortletId());
log(p);
log(p.getDisplayName());
log(p.getInitParams());
}
String c = request.getParameter("clink");
log(c);
if(c != null && (c.equals("g") || c.equals("y") || c.equals("d") || c.equals("w"))) {
String portletId = layoutTypePortlet.addPortletId(Long.parseLong(request.getRemoteUser()), PortletKeys.IFRAME, "column-2", -1);
log("portletId: "+portletId);
long companyId = themeDisplay.getCompanyId();
long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
Layout layout = themeDisplay.getLayout();
PortletPreferences prefs = PortletPreferencesLocalServiceUtil.getPreferences(companyId, ownerId, ownerType, layout.getPlid(), portletId);
Locale locale = new Locale("en", "US");
prefs.setValue("portlet-setup-use-custom-title", "true");
if(c.equals("g")) {
prefs.setValue("src","http://www.google.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Google");
}
else if(c.equals("y")) {
prefs.setValue("src","http://www.yahoo.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Yahoo");
}
else if(c.equals("d")) {
prefs.setValue("src", "http://www.dailytech.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Daily Tech");
}
else if(c.equals("w")) {
prefs.setValue("src", "http://www.wired.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Wired");
}
PortletPreferencesLocalServiceUtil.updatePreferences(ownerId, ownerType, layout.getPlid(), portletId, prefs);
portletList = layoutTypePortlet.getPortlets();
for(Portlet p : portletList) {
if(p.getPortletId().equals(portletId)) {
break;
}
}
LayoutLocalServiceUtil.updateLayout(layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(), layout.getTypeSettings());
}
}
catch(Exception e) {
log("LinksPortlet:doView:Exception");
e.printStackTrace();
}
super.render(request, response);
}
The issue with the above implementation is that the new portlet appears on the screen after the page reload:
http://www.go-ahead.in/books/1.JPG
http://www.go-ahead.in/books/2.JPG
http://www.go-ahead.in/books/3.JPG
The reason for the issue is that the new portlet is added after the layout render starts. Is it possible to customize or add a hook for performing the action I am performing during page / layout load. I came across the source LayoutAction.java of liferay where portlets are added. Is there any way to add a post hook to add the portlet without modifying the liferay's source code?
I am using Liferay 6.0.5.
Thanks in advance.
Found the solution to the problem.
I have moved the code from render method to processAction and creating the link using <portlet:actionURL> tag.