navigation bar can't hide xamarin forms - xaml

this my DetailsPage
public DetailsPage(Property property)
{
Xamarin.Forms.NavigationPage.SetHasNavigationBar(this, false);
Xamarin.Forms.NavigationPage.SetHasBackButton(this, false);
InitializeComponent();
this.Property = property;
this.BindingContext = this;
}
and in my XAML code, I have added these lines
NavigationPage.HasNavigationBar="False"
NavigationPage.HasBackButton="False"
but can't hide the navigation bar in detailspage

I have noticed that doing this on your customized base page or just basically on the XAML works better than doing it in code where you might, unknowingly change it in the wrong place do what I do is this
<ContentPage
x:Class="Proj.BaseContentPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
NavigationPage.HasBackButton="False"
NavigationPage.HasNavigationBar="False">
Goodluck feel free to get back if you have questions

this is my content page
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App6.DetailsPage"
NavigationPage.HasBackButton="False"
NavigationPage.HasNavigationBar="False"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pv="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
>
and this is my InitializeComponent();
public DetailsPage(Property property)
{
Xamarin.Forms.NavigationPage.SetHasNavigationBar(this, false);
Xamarin.Forms.NavigationPage.SetHasBackButton(this, false);
InitializeComponent();
this.Property = property;
this.BindingContext = this;
//idds = property.Id.ToString();
//idd = Property.Id.ToString();
//alert( idd);
}
but my navigation panel doesn't was hidden

Related

Xamarin : An element with the key 'X' already exists in NameScope

I'm getting the following error when I try to push to a new page.
(I'm using Xamarin.Form 4.6.0.800)
{System.ArgumentException: An element with the key 'NewAccountLogo' already exists in NameScope
Parameter name: name
at Xamarin.Forms.Internals.NameScope.Xamarin.Forms.Internals.INameScope.RegisterName (System.String name, System.Object scopedElement) [0x0000e] in D:\a\1\s\Xamarin.Forms.Core\Internals\NameScope.cs:21
at amici.NewAccount.InitializeComponent () [0x00078] in C:\Users\X\source\repos\amici\amici\amici\obj\Debug\netstandard2.0\NewAccount.xaml.g.cs:46
at amici.NewAccount..ctor () [0x0000f] in C:\Users\X\source\repos\amici\amici\amici\NewAccount.xaml.cs:26
at amici.Logon+<OnCreateAccountClick>d__3.MoveNext () [0x0002a] in C:\Users\X\source\repos\amici\amici\amici\logon.xaml.cs:119 }
The error seems straight forward so I went back and renamed the element and then searched my project for the same name. (there is only one). Recompiled and tried it again, same message but with the new name? so I delete the element and tried recompiled and tried it again, interesting enough I get the same message but with the next element? So now I’m thinking maybe the error message is not quite right or is trying to tell me something else. I just can’t figure it out. Below is my xaml.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
NavigationPage.HasNavigationBar="True"
Title="New Account"
x:Class="amici.NewAccount">
<ContentPage.Content >
<ScrollView>
<Grid>
<StackLayout Margin="20" Padding="10" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<Image x:Name="NewAccountLogo"/>
<Entry x:Name="NewEmail" Placeholder="Email"/>
<Entry x:Name="EmailConfirm" Placeholder="Confirm Email"/>
<Label Text="Password between 6 and 20 characters; must contain at least one lowercase letter, one uppercase letter, one numeric digit." Margin="0,0,0,5"></Label>
<Entry x:Name="NewPassword" IsPassword="true" Placeholder="Password"/>
<Entry x:Name="PasswordConfirm" IsPassword="true" Placeholder="Confirm Password"/>
<Label x:Name="bntCreatAccountButton" TextColor="Blue" Text="Create Account" HorizontalOptions="Center" Margin="0,25,0,0">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnCreateAccount" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
<ActivityIndicator x:Name="WaitIcon" IsRunning="{Binding IsBusy}" VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
</ScrollView>
</ContentPage.Content>
</ContentPage>
code behind :
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class NewAccount : ContentPage
{
public NewAccount()
{
InitializeComponent ();
this.InitializeComponent();
this.BindingContext = this;
this.IsBusy = false;
var bkgrndGradient = new Gradient()
{
Rotation = 150,
Steps = new GradientStepCollection()
{
new GradientStep(Color.White, 0),
new GradientStep(Color.White, .5),
new GradientStep(Color.FromHex("#ccd9ff"), 1)
}
};
ContentPageGloss.SetBackgroundGradient(this, bkgrndGradient);
NewAccountLogo.Source = ImageSource.FromFile("logo.png");
}
async private void OnCreateAccount(object sender, EventArgs e)
{
string Message = string.Empty;
string title = string.Empty;
bool results = false;
IsBusy = true;
try
{
if (ComparisonBehavior.CompareValues(NewEmail.Text, NewPassword.Text, EmailConfirm.Text,PasswordConfirm.Text, ref Message, ref title))
{
await Task.Delay(1000);
results = RestController.CreateAccount(NewEmail.Text, NewPassword.Text);
IsBusy = false;
if (results)
{
await DisplayAlert("New Account Created.", "Thank You! Please check your email (junk mail) to activate your subscription.", "OK");
await Application.Current.MainPage.Navigation.PopAsync();
}else
{
if (Application.Current.Properties["resp"].ToString() == "Account exist")
{
await DisplayAlert("Account Exist", "Sorry this email already exist!", "OK");
}
}
}else
{
await DisplayAlert(title, Message, "OK");
}
}catch (Exception ex)
{
await DisplayAlert("internal Error", ex.Message, "OK");
} finally{
IsBusy = false;
}
}
}
any help would be appreciated.
Mike
In my Code behind I had InitializeComponent (); declared twice.
This type of issue generally happens when the system tries to Initialize the same components with the same name. Please check InitializeComponent(); maybe, it has declared twice.
In my case I was trying to bind a component to its' code behind class instead of its' view model. I was doing:
<Picker
BindingContext={x:Reference x:Name=ThisPage}
/>
The problem was that x:Name=ThisPage was actually trying to set a new name for X Namespace instead of referencing one, when I changed it to Name=ThisPage it worked fine.

How to display a label with click on listview

I want to show a label when i click on my item in my listview.
The real problem i don't know how to link between my viewmodel and my views
I want modify my label in viewmodel but I don't know if its possible currently.
My xaml :
<StackLayout>
<Label x:Name="labelperso"
Text="{Binding newProduct}"
IsVisible="{Binding Addproduct}"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
BackgroundColor="#000000"
FontSize="20"
Opacity="0"/>
<ListView ItemsSource="{Binding Products}" CachingStrategy="RecycleElement" RowHeight="50" >
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding CodeReferenceLibelle}" TextColor="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemSelected" Command="{Binding
SelectCommand}" Converter="{StaticResource SelectedItemConverter}"/>
</ListView.Behaviors>
my viewmodel :
#region labelperso property
private string _newProduct;
public string newProduct
{
get { return _newProduct; }
set { SetProperty(ref _newProduct, value); }
}
#endregion
#region Addproduct property
private bool _Addproduct;
public bool Addproduct
{
get { return _Addproduct; }
set { SetProperty(ref _Addproduct, value); }
}
#endregion
when I click on my item :
async Task Select()
{
newProduct = "Produit ajouté !";
basketManager.AddProductSkuAsync(sku);
newProduct = "";
await Task.Run(() => ShowText());
}
//I have tried this but I can't use my label in my view
async Task ShowText()
{
await labelperso.FadeTo(1);
await Task.Delay(1000);
await labelperso.FadeTo(0);
}
Why are you want to take the label "labelperso" in VM ? you can use it in xaml.cs instead.
You just need to add the event ItemSelected like this:
<ListView ItemsSource="{Binding Products}" ItemSelected="OnSelection">
In xaml.cs
void OnSelection(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
//suppose the binding Object is Product
Product product = (Product)e.SelectedItem;
//labelperso.Text = "name = " + product.Name;
labelperso.FadeTo(1);
Task.Delay(1000);
labelperso.FadeTo(0);
}
Normally, VM are unrelated to Xaml, and we should not get labels from VM.
And we don't recommend it.But if you must, you can pass the Label in from the xaml.cs file like this:
You can define a variable in yourpage.xaml.cs:
public Label pageLabel;
and initial like this:
pageLabel = labelperso;
BindingContext = new YourViewmodel(this);
And in YourViewmodel.cs:
public Label ss;
public YourViewmodel(ContentPage parentPage)
{// here HomePage is your contentPage name of the page`
ss = ((HomePage)parentPage).pageLabel;//after this you can use it
}
You need to add a SelectedProduct property to your VM.
private string _SelectedProduct;
public string SelectedProduct
{
get { return _SelectedProduct; }
set { SetProperty(ref _SelectedProduct, value); }
}
You can then bind your ListView's SelectedItem to it
<ListView ItemsSource="{Binding Products}"
SelectedItem="{Binding SelectedProduct}"
CachingStrategy="RecycleElement"
RowHeight="50" >
You can then control the visibility of your label by binding to SelectedProduct via a "nullToVisibility" converter, or by using triggers etc.
You should try to use MVVM pattern rather than hacking with code behind.
Using MVVM you can add a Visible property to your viewmodel and bind the IsVisible property of the label to it.
Code will be much easy to read and maintain.

Scrolling screen towards up when keypad open on login page Xamarin

I am working on Xamarin.Forms. I have login page for that I am using StackLayout with ScrollView.
Code following
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="simpleListView.Pages.LoginPage">
<ContentPage.Content>
<ScrollView Orientation="Vertical" x:Name="scroll">
<StackLayout Padding="20">
<Label Margin="20" HorizontalOptions="Center" Text="Login below" ></Label>
<BoxView HeightRequest="150" Color="Accent"></BoxView>
<Entry Text="{Binding Email}" x:Name="txtEmail" Placeholder="Email"></Entry>
<Entry Text="{Binding Password}" x:Name="txtPass" Placeholder="Paasword"></Entry>
<Button x:Name="btnLogin" BackgroundColor="Blue" Text="Login" Command="{Binding SubmitCommand}"></Button>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
But the code above not scrolling layout towards top when keypad open & hiding almost half of Login button. How can I implement scrolling when keypad open? I am not much interested in using custom renderers.
See login page screeshot
Since there is (as far as I am informed) no good way to get the actual keyboard height for android via a DependencyService, using that scrollview is the right approach to begin with, however what you want to do is UI customizing which leads to custom renderers. Saying "i want a cool custom UI but I am not interested in custom renderers" is like "I want to drive, but I am not interested in wheels".
However, to make it a bit easier for you, I happen to have code for a custom renderer, which gives the desired result:
Android
[assembly: ExportRenderer(typeof(ModernLogin), typeof(ModernLoginPageRenderer))]
namespace MyApp.Droid.Renderer
{
public class ModernLoginPageRenderer : PageRenderer
{
public ModernLoginPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
// Set SoftInput.AdjustResize for this window
if (e.NewElement != null)
{
(this.Context as FormsApplicationActivity).Window.SetSoftInputMode(SoftInput.AdjustResize);
}
}
protected override void OnWindowVisibilityChanged([GeneratedEnum] ViewStates visibility)
{
// Revert to default SoftInputMode after moving away from this window
if (visibility == ViewStates.Gone)
{
(this.Context as FormsApplicationActivity).Window.SetSoftInputMode(SoftInput.AdjustPan);
}
base.OnWindowVisibilityChanged(visibility);
}
protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
{
base.OnLayout(changed, left, top, right, bottom);
}
}
}
iOS
[assembly: ExportRenderer(typeof(ModernLogin), typeof(ModernLoginPageRenderer))]
namespace MyApp.iOS.Renderer
{
public class ModernLoginPageRenderer : PageRenderer
{
NSObject observerHideKeyboard;
NSObject observerShowKeyboard;
public override void ViewDidLoad()
{
base.ViewDidLoad();
var cp = Element as ModernLogin;
if (cp != null)
{
foreach (var g in View.GestureRecognizers)
{
g.CancelsTouchesInView = true;
}
}
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
observerHideKeyboard = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, OnKeyboardNotification);
observerShowKeyboard = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardNotification);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NSNotificationCenter.DefaultCenter.RemoveObserver(observerHideKeyboard);
NSNotificationCenter.DefaultCenter.RemoveObserver(observerShowKeyboard);
}
void OnKeyboardNotification(NSNotification notification)
{
if (!IsViewLoaded) return;
var frameBegin = UIKeyboard.FrameBeginFromNotification(notification);
var frameEnd = UIKeyboard.FrameEndFromNotification(notification);
var page = Element as ModernLogin;
if (page != null)
{
var padding = page.Padding;
page.Padding = new Thickness(padding.Left, padding.Top, padding.Right, padding.Bottom + frameBegin.Top - frameEnd.Top);
}
}
}
}
Make sure you replace the name of "ModernLogin" with the name of your login page class. If your LoginPage is a regular ContentPage, I would recommend creating a new class inheriting from ContentPage.

Xamarin form app: Keyboard type telephone allow to input negative values in Android but not in IOS

I have made an application in Xamarin From. Design the UI in xaml. My issue is when i define the Keyboard telephone in entry field it allow to input negative value in android app but in IOS it not allowed.
<StackLayout Spacing="20" Padding="0" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Entry Text="{Binding Item.TextProvider2017}" HorizontalTextAlignment="End" FontSize="Small" WidthRequest="140" MinimumWidthRequest="60" Placeholder="For 2017" Keyboard="Telephone" Completed="NoOfProvider_Completed" Unfocused="NoOfProvider_Unfocused"/>
<Entry Text="{Binding Item.TextProvider2018}" HorizontalTextAlignment="End" FontSize="Small" WidthRequest="140" MinimumWidthRequest="60" Placeholder="For 2018" Keyboard="Telephone"/>
<Entry Text="{Binding Item.TextProvider2019}" HorizontalTextAlignment="End" FontSize="Small" WidthRequest="140" MinimumWidthRequest="60" Placeholder="For 2019" Keyboard="Telephone"/>
<Entry Text="{Binding Item.TextProvider2020}" HorizontalTextAlignment="End" FontSize="Small" WidthRequest="140" MinimumWidthRequest="60" Placeholder="For 2020" Keyboard="Telephone"/>
</StackLayout>
Keypad in Android:
Keypad in IOS:
In Android keypad have negative sign but IOS don't have. IS there any way to make both same.
This is the old answer, see below for an updated version
You're going to want to create a custom renderer for the Entry control which has the default behavior for UWP and Android, while adding a custom InputAccessoryView to your iOS UITextField.
Here's what your custom renderer for iOS might look like:
class MinusButtonEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control == null) return;
UIBarButtonItem button = new UIBarButtonItem("-", UIBarButtonItemStyle.Plain, (sender, args) =>
{
var position = Control.SelectedTextRange.Start;
var idx = (int) Control.GetOffsetFromPosition(Control.BeginningOfDocument, position);
Element.Text.Insert(idx, "-");
});
UIToolbar toolbar = new UIToolbar()
{
Items = new [] { button }
};
Control.InputAccessoryView = toolbar;
}
}
This code basically creates a button, adds that to a toolbar, and then assigns that toolbar to the underlying UITextField. You will of course want to customize the toolbar and toolbar button to suit your needs.
EDIT:
There's a better way to do this using Effects in Xamarin Forms.
This class goes in the iOS project and is the main effect:
using MyApp;
using UIKit;
using Xamarin.Forms;
[assembly:ResolutionGroupName("Xamarin")]
[assembly:ExportEffect(typeof(MinusButtonEntryEffect), "MinusButtonEntryEffect")]
namespace MyApp
{
public class MinusButtonEntryEffect : PlatformEffect<UIView, UITextField>
{
protected override void OnAttached()
{
if (Control == null) return;
var element = Element as Entry;
if (element == null) return;
UIBarButtonItem button = new UIBarButtonItem("-", UIBarButtonItemStyle.Plain, (sender, args) =>
{
var position = Control.SelectedTextRange.Start;
var idx = (int)Control.GetOffsetFromPosition(Control.BeginningOfDocument, position);
element.Text = element.Text.Insert(idx, "-");
});
UIToolbar toolbar = new UIToolbar()
{
Items = new[] { button }
};
Control.InputAccessoryView = toolbar;
}
protected override void OnDetached()
{
Control.InputAccessoryView = null;
}
}
}
This code goes in the PCL and allows us to access the effect from XAML:
public class MinusButtonEntryEffect : RoutingEffect
{
public MinusButtonEntryEffect () : base ("Xamarin.MinusButtonEntryEffect") { }
}
So your XAML would look something like this:
<Entry Text="{Binding Item.TextProvider2017}" HorizontalTextAlignment="End" FontSize="Small" WidthRequest="140" MinimumWidthRequest="60" Placeholder="For 2017" Keyboard="Telephone">
<Entry.Effects>
<local:MinusButtonEntryEffect />
</Entry.Effects>
</Entry>
Make sure that local is whatever namespace your effect is in, for example:
xmlns:local="clr-namespace:MyApp"

"Hello World" with ReactiveUI, Xamarin Forms and XAML locking up

I'm trying to do a hello world with Reactive UI and Xamarin Forms.
I have created a ViewModel (based on ReactiveObject), a custom page (based on ReactiveContentPage) and some XAML markup.
The page has an entry and a Label, bound together. When I run it (on iOS and Android), it appears to work for the first few characters typed, then locks up. The console gives a 'too much is happening on the main thread' warning.
What am I missing?
The project is here.
The Model
namespace XamarinFormsReactiveUIExample
{
public class MyPageModel : ReactiveObject
{
private string _userName = "";
public string UserName {
get { return _userName; }
set { this.RaiseAndSetIfChanged (ref _userName, value); }
}
}
}
The Page
namespace XamarinFormsReactiveUIExample
{
public partial class MyPage : ReactiveContentPage<MyPageModel>
{
public MyPage ()
{
InitializeComponent ();
}
}
}
The XAML
<?xml version="1.0" encoding="UTF-8"?>
<reactive:ReactiveContentPage
x:TypeArguments="local:MyPageModel"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsReactiveUIExample.MyPage"
xmlns:local="clr-namespace:XamarinFormsReactiveUIExample;assembly=XamarinFormsReactiveUIExample"
xmlns:reactive="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms">
<reactive:ReactiveContentPage.BindingContext>
<local:MyPageModel />
</reactive:ReactiveContentPage.BindingContext>
<reactive:ReactiveContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 150, 0, 0" />
</reactive:ReactiveContentPage.Padding>
<reactive:ReactiveContentPage.Content>
<StackLayout>
<Entry Text = "{Binding UserName}"></Entry>
<Label Text = "{Binding UserName}"></Label>
</StackLayout>
</reactive:ReactiveContentPage.Content>
</reactive:ReactiveContentPage>
I don't see how this could be anything but a Xamarin bug, ReactiveUI isn't doing anything here. Anyways, you can always try to write these bindings the RxUI way:
<Entry x:Name="userNameEntry" />
<Label x:Name="userNameLabel" />
Then, in the constructor:
public MyPage ()
{
InitializeComponent();
this.ViewModel = new MyPageModel();
this.Bind(ViewModel, vm => vm.UserName, v => v.userNameEntry.Text);
this.OneWayBind(ViewModel, vm => vm.UserName, v => v.userNameLabel.Text);
}
The only thing I saw missing was the ViewModel was never instantiated, and the Binding Context was never set. I can't see what your old code did before you changed it to the new style. Personally, I try to avoid using code behind as much as possible as well. So you should be able to modify your constructor to something like,
public MyPage ()
{
InitializeComponent();
this.ViewModel = new MyPageModel();
this.BindingContext = ViewModel;
}
And revert to using your XAML binding.