I have a project with a MasterDetailPage as root page. When I navigate deeper inside the Detailpage, I have the problem, that the DetailPage navigation overrides my actionbar for the MasterPage. Can I have both in the actionbar, the burgermenuicon and the backbutton?
before navigation:
after navigation:
public partial class MasterPage : MasterDetailPage
{
public MasterPage()
{
Master = SetMasterContentPage();
Detail = new NavigationPage(new TaxonomyOverviewPage());
}
ContentPage SetMasterContentPage()
{
var masterPage = new ContentPage { Title = "Test"};
masterPage.Content = new StackLayout
{
Children = {
new Label{Text="Label1"},
new Label{Text="Label2"},
new Label{Text="Label3"}
}
};
return masterPage;
}
protected override void OnAppearing()
{
base.OnAppearing();
}
}
Problem is solved.
I used a public static MasterDetailPage and referenced it to the MainPage in App.cs. Now I can access the IsPresented property of the MasterDetailPage.
public partial class App : Application
{
public static MasterPage masterdetail;
public App()
{
InitializeComponent();
}
protected override void OnStart()
{
masterdetail = new MasterPage();
Device.BeginInvokeOnMainThread(() => {
MainPage = masterdetail;
});
}
}
Finally, I add a menuicon to the right side of the actionbar.
protected override void OnAppearing()
{
base.OnAppearing();
ToolbarItems.Add(new ToolbarItem("Menu", "menuicon.png", () => { App.masterdetail.IsPresented = true; }));
}
Related
App.xaml.cs
MainPage = new NavigationPage(new Home());
Home.xaml.cs
public partial class Home : CarouselPage
{
public Home()
{
Children.Add(new CarPage1());
Children.Add(new CarPage2());
CurrentPage = new CarPage2();
}
}
CarPage2.xaml.cs
public partial class CarPage2 : ContentPage
{
public CarPage2()
{
InitializeComponent();
}
private void Btn_Clicked(object sender, EventArgs e)
{
//Do something
//I wanna change screen to CarPage1 without use Navigation.PushAsync(new CarPage1());
}
}
How to change current screen to CarPage1 not use Navigation.PushAsync ?
I have done a sample to test and setting the CurrentPage property worked correctly, you can try the following code:
public partial class CarPage2 : ContentPage
{
public CarPage2()
{
InitializeComponent();
}
private void Btn_Clicked(object sender, EventArgs e)
{
var home = this.Parent as CarouselPage;
home.CurrentPage = home.Children[0];
}
}
I have this code:
using System;
using Xamarin.Forms;
namespace Test
{
public partial class ScrollHeadingView : ContentPage
{
public ScrollHeadingView()
{
// more code here
if (RightIconVisible)
{
// do some actions to add elements to each other here
var rightIconPageHeadingSvg = new PageHeadingSvg() { HorizontalOptions = LayoutOptions.StartAndExpand }
.Bind(PageHeadingSvg.SourceProperty, nameof(RightIconSource), source: this);
grid3.AddChild(rightIconPageHeadingSvg);
grid2.GestureRecognizers.Add(rightIconTap);
grid3.AddChild(rightIconPageHeadingSvg);
}
}
}
and
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage()
{
RightIconVisible = true;
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}
I am setting RightIconVisible to true and want that to be reflected in ScrollHeadingView when it is constructed.
But it's not happening.
Is there a way that I can set this to happen with code in DecksTabPage?
Note that if I was using XAML I would have done this by binding to the IsVisible of a grid and then set the IsVisible to show or not show that code that has the elements. But as I am using C# I am not sure how to do this.
Constructor of parent class works before any code in constructor of child class.
To pass some value to parent class constructor, you should add a constructor parameter to it and call base constructor from child with needed value.
For example:
public partial class ScrollHeadingView : ContentPage
{
public ScrollHeadingView(bool rightIconVisible = false)
{
RightIconVisible = rightIconVisible;
if (RightIconVisible)
{
// do some actions to add elements to each other here
}
}
}
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage():base(true)
{
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}
Other possibility is to remove code working with RightIconVisible from parent class constructor and put it into set of corresponding property.
public partial class ScrollHeadingView : ContentPage
{
private bool rightIconVisible;
public ScrollHeadingView()
{}
protected bool RightIconVisible
{
get => rightIconVisible;
set
{
rightIconVisible = value;
if (rightIconVisible)
{
// do some actions to add elements to each other here
}
}
}
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage()
{
RightIconVisible = true;
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}
I order to have a cutom navigation on a specific view on my app,
I create a Custom Navigation ios:
public class CustomNavigationPageRenderer : NavigationRenderer
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
UINavigationBar.Appearance.ShadowImage = new UIImage();
UINavigationBar.Appearance.BackgroundColor = UIColor.Clear;
UINavigationBar.Appearance.TintColor = UIColor.White;
UINavigationBar.Appearance.BarTintColor = UIColor.Clear;
UINavigationBar.Appearance.Translucent = true;
}
}
and a common interface class:
public partial class CustomPage : NavigationPage
{
public CustomPage(): base()
{
InitializeComponent();
}
public CustomPage(Page root) : base(root)
{
InitializeComponent();
}
public bool IgnoreLayoutChange { get; set; } = false;
protected override void OnSizeAllocated(double width, double height)
{
if (!IgnoreLayoutChange)
base.OnSizeAllocated(width, height);
}
}
Now, In my specific view, how have I use it?
I need to set on false the original navigation? (NavigationPage.SetHasNavigationBar(this, false);)
public MySpecificViewNeedCustoNAv()
{
CustomPage myNavigationPage = new CustomPage();
...
need to set on false the original navigation?
No , you can refer the following code.
For example
Creating the Root Page in App.cs
public App ()
{
MainPage = new CustomPage (new xxxpage());
}
Pushing Pages to the Navigation Stack in your page
async void ButtonClicked (object sender, EventArgs e)
{
await Navigation.PushAsync (new xxxpage());
}
My C# looks like this:
public App()
{
InitializeComponent();
MainPage = new Japanese.MainPage();
}
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
var phrasesPage = new NavigationPage(new PhrasesPage())
{
Title = "Play",
Icon = "ionicons-2-0-1-ios-play-outline-25.png"
};
public partial class PhrasesPage : ContentPage
{
public PhrasesFrame phrasesFrame;
public PhrasesPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
App.phrasesPage = this;
}
protected override void OnAppearing()
{
base.OnAppearing();
App.dataChange = true;
phrasesFrame = new PhrasesFrame(this);
phrasesStackLayout.Children.Add(phrasesFrame);
}
public partial class PhrasesFrame : Frame
{
private async Task ShowCard()
{
if (pauseCard == false)
..
and I have an iOS renderer for a tab page
public class TabbedPageRenderer : TabbedRenderer
{
private MainPage _page;
private void OnTabBarReselected(object sender, UITabBarSelectionEventArgs e)
{
...
pauseCard = false;
...
My problem is there is no connection between the two and I would like to know how I can make it so that pauseCard could be set in one place and read in another.
Here is a simple custom Entry example using a bindable bool property that gets changed from the renderer every time the text changes in the entry.
Entry subclass w/ a bindable property called OnOff (bool)
public class CustomPropertyEntry : Entry
{
public static readonly BindableProperty OnOffProperty = BindableProperty.Create(
propertyName: "OnOff",
returnType: typeof(bool),
declaringType: typeof(CustomPropertyEntry),
defaultValue: false);
public bool OnOff
{
get { return (bool)GetValue(OnOffProperty); }
set { SetValue(OnOffProperty, value); }
}
}
iOS Renderer
Note: I keep a reference to the instance of the CustomPropertyEntry passed into OnElementChanged so later I can set its custom property when needed.
public class CustomPropertyEntryRenderer : ViewRenderer<CustomPropertyEntry, UITextField>
{
UITextField textField;
CustomPropertyEntry entry;
protected override void OnElementChanged(ElementChangedEventArgs<CustomPropertyEntry> e)
{
base.OnElementChanged(e);
if (Control == null)
{
textField = new UITextField();
SetNativeControl(textField);
}
if (e.OldElement != null)
{
textField.RemoveTarget(EditChangedHandler, UIControlEvent.EditingChanged);
entry = null;
}
if (e.NewElement != null)
{
textField.AddTarget(EditChangedHandler, UIControlEvent.EditingChanged);
entry = e.NewElement;
}
}
void EditChangedHandler(object sender, EventArgs e)
{
entry.OnOff = !entry.OnOff;
}
}
XAML Example:
<local:CustomPropertyEntry x:Name="customEntry" Text="" />
<Switch BindingContext="{x:Reference customEntry}" IsToggled="{Binding OnOff}" />
When I click on Login for the first time than the barbackground of mainpage becomes the right color, but when I logout and than login again the color of the barbackground doesn't change??
LoginPage (View)
public partial class LoginPage : ContentPage
{
LoginPageViewModel vm;
public LoginPage ()
{
vm = new LoginPageViewModel ();
BindingContext = vm;
InitializeComponent ();
}
public void OnClickLogin(object o, EventArgs e)
{
vm.Login ();
}
public void OnClickPasswoordVergeten(object o, EventArgs e)
{
vm.PasswoordVergeten ();
}
public void OnClickContactUs(object o, EventArgs e)
{
vm.ContactUs ();
}
}
LoginPageViewModel (ViewModel)
public class LoginPageViewModel: INotifyPropertyChanged
{
public LoginPageViewModel ()
{
}
public void Login()
{
App.Current.MainPage = new Dharma.MainPage();
}
}
MainPage (View)
public partial class MainPage : MasterDetailPage
{
public MainPage ()
{
InitializeComponent ();
masterPage.ListView.ItemSelected += OnItemSelected;
var page = new NavigationPage (new ListPage());
page.BarBackgroundColor = Color.FromRgb(26,179,148);
Detail = page;
masterPage.ListView.SelectedItem = null;
IsPresented = false;
}
void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MasterPageItem;
if (item != null) {
var page = new NavigationPage ((Page)Activator.CreateInstance (item.TargetType));
page.BarBackgroundColor = Color.FromRgb(26,179,148);
Detail = page;
masterPage.ListView.SelectedItem = null;
IsPresented = false;
}
}
}
Set the color to your master page.
public void Login()
{
var mainPage = new Dharma.MainPage();
mainPage.BarBackgroundColor = Color.FromRgb(26,179,148);
App.Current.MainPage = mainPage ;
}