[![enter image description here][1]][1]This is the MainPage which has a navigation Bar that contains 4 barItems.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Title="CheckList"
x:Class="mmy.View.MainPage">
<ContentPage.ToolbarItems>
<ToolbarItem Name="MenuItem1" Order="Primary" Icon="itemIcon1.png" Priority="0" />
<ToolbarItem Name="MenuItem2" Order="Primary" Icon="itemIcon2.png" Priority="1" />
<ToolbarItem Name="MenuItem1" Order="Primary" Icon="itemIcon3.png" Priority="2" />
<ToolbarItem Name="MenuItem2" Order="Primary" Icon="itemIcon4.png" Priority="3" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Label Text="MainPage"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
The Navigation Bar will look like below:
-------------------------------------------------------
Main barItem1 | barItem2 | barItem3 | barItem4
-------------------------------------------------------
Item1_Content
Say , I have 4 bar items in the Navigation bar
I want to do the following:
When user click barItem2 ,
a) it will bring in a Item2_Content which will replace the Item1_Content. ( I m not sure there is such UI )
b) the barItem (1 to 4 ) still remain in the navigation bar.
Is this doable?
Can you help me how to implement such user requirement?
Thanks
Update:
--(1) - start at P1 :
private async void BtnLogin_Clicked(object sender, EventArgs e)
{
NavigationPage NP = new NavigationPage(new MainPage())
{
BarBackgroundColor = Color.White,
BarTextColor = Color.DarkGray
};
}
--(2) I created a new page call RepairSvc for (3)
--(3) At MainPage : it has a navigation bar from (1)
Click the Icon="itemIcon1.png"
<ToolbarItem Name="MenuItem1" Order="Primary" Icon="itemIcon1.png" Command="Item1Command" Priority="0" />
Code Behind :
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
public ICommand Item1Command { get; private set; }
public MainPage()
{
InitializeComponent();
this.Item1Command = new Command((sender) =>
{
Navigation.PushAsync(new RepairSvc());
});
}
}
assign a command to your toolbar
<ToolbarItem Name="MenuItem1" Order="Primary" Icon="itemIcon1.png" Priority="0" Command="Item1Command" />
in your codebehind
this.Item1Command = new Command((sender) =>
{
Navigation.PushAsync(new MyPage());
});
}
public ICommand Item1Command { get; private set; }
Related
I would like to have a property in my ViewModel that is linked to my StackLayout. I tried this by Binding my StackLyout to the ViewModel.
When I click on a button, this layout should be made invisible.
When I do this with the code below, my program crashes with a NulReferenceObject: Object Reference not set to an instance of an object. The StackLayout that i am talking about is the first one in the code below.
<FlexLayout>
<StackLayout BindableLayout.ItemTemplate="{Binding CreateQuizPageQuizNameSL}"> // This StackLayout should be bind to the ViewModel
<Label Text="Create New Quiz" />
<StackLayout >
<Entry Text="{Binding QuizNameInput}" Placeholder="Enter quiz name"/>
</StackLayout>
</StackLayout>
<Button Command="{Binding SubmitCreateQuizCommand}" Text="Create my quiz now!"></Button>
</FlexLayout>
ViewModel
internal class CreateQuizPageViewModel
{
// Quiz Name Input
public String QuizNameInput { get; set; }
// Command submit creating a quiz
public Command SubmitCreateQuizCommand { get; set; }
public StackLayout CreateQuizPageQuizNameSL { get; set; } = new StackLayout();
public CreateQuizPageViewModel()
{
// Declaring a new command, giving the OnSubmitCreateNewQuizClick to the delegate
SubmitCreateQuizCommand = new Command(OnSubmitCreateNewQuizClick);
}
// When a user submit the creation of new quiz
public void OnSubmitCreateNewQuizClick()
{
CreateQuizPageQuizNameSL.IsVisible = false;
}
}
Here is how to switch two layouts using IsVisible binding.
FIRST Add Nuget Xamarin.CommunityToolkit to your Xamarin Forms project. (The one that is "MyProjectName", without ".iOS" or ".Android" at end.)
TwoLayoutPage.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"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:local="clr-namespace:TestBugs"
x:Class="TestBugs.TwoLayoutPage">
<ContentPage.BindingContext>
<local:TwoLayoutViewModel/>
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<xct:InvertedBoolConverter x:Key="InvertedBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<StackLayout
IsVisible="{Binding UseSecondLayout, Converter={StaticResource InvertedBoolConverter}}"
VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label Text="First Layout" FontSize="20" />
<Button Text="To Second" Command="{Binding SwitchToSecondLayoutCommand}" />
</StackLayout>
<StackLayout IsVisible="{Binding UseSecondLayout}"
VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label Text="Second Layout!" FontSize="32" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
TwoLayoutViewModel.cs:
using Xamarin.Forms;
namespace TestBugs
{
public class TwoLayoutViewModel : BindableObject
{
private bool _usesecondLayout = false;
public bool UseSecondLayout {
get => _usesecondLayout;
set {
_usesecondLayout = value;
OnPropertyChanged();
}
}
public TwoLayoutViewModel()
{
SwitchToSecondLayoutCommand = new Command(SwitchToSecondLayout);
}
public Command SwitchToSecondLayoutCommand { get; set; }
private void SwitchToSecondLayout()
{
UseSecondLayout = true;
}
}
}
I have a simple Xamarin.Forms app with a main page as TabbedPage which looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage
x:Class="PrismSample.Views.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
xmlns:views="clr-namespace:PrismSample.Views"
Title="Main Page"
prism:ViewModelLocator.AutowireViewModel="True">
<TabbedPage.Children>
<NavigationPage Title="Page1">
<x:Arguments>
<views:OnePage Title="Page 1" />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Page2">
<x:Arguments>
<views:TwoPage Title="Page 2" />
</x:Arguments>
</NavigationPage>
</TabbedPage.Children>
</TabbedPage>
On the page "OnePage" I have a button. When I tap on that button I want to navigate to a page named "ThreePage".
OnPage:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
x:Class="PrismSample.Views.OnePage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True">
<ContentPage.Content>
<StackLayout Margin="20" Spacing="20">
<Label HorizontalOptions="CenterAndExpand" Text="Page 1" />
<Button
x:Name="Button1"
Command="{Binding ClickMeCommand}"
HorizontalOptions="FillAndExpand"
Text="Open Page 3" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
OnePageViewModel:
namespace PrismSample.ViewModels
{
public class OnePageViewModel : BindableBase
{
private readonly INavigationService navigationService;
public DelegateCommand ClickMeCommand { private set; get; }
public OnePageViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
ClickMeCommand = new DelegateCommand(async () => await ClickedAsync(), () => true);
Debug.WriteLine($"NavigationStack: {this.navigationService.GetNavigationUriPath()}", nameof(OnePageViewModel));
}
public Task ClickedAsync()
{
Debug.WriteLine($"You clicked me!", nameof(OnePageViewModel));
return navigationService.NavigateAsync("ThreePage");
}
}
}
App.xaml.cs
namespace PrismSample
{
public partial class App
{
public App() : this(null) { }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override async void OnInitialized()
{
InitializeComponent();
var result = await NavigationService.NavigateAsync("MainPage");
if(!result.Success)
{
System.Diagnostics.Debugger.Break();
}
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
containerRegistry.RegisterForNavigation<OnePage, OnePageViewModel>();
containerRegistry.RegisterForNavigation<TwoPage, TwoPageViewModel>();
containerRegistry.RegisterForNavigation<ThreePage, ThreePageViewModel>();
}
}
}
I expected the following:
When tapping on the button a navigation to the page "ThreePage" is done within the first tab. I also expected to have a "Back" button in the navigation bar.
What happens:
Nothing in the first tab. But if I switch to the second tab it shows the page "ThreePage" but also without a "Back" button.
What is going wrong here???
I have attached my project here:
https://www.dropbox.com/s/fuu2wo5zqhp52gk/08-TabbedNavigation.zip?dl=0
Navigating via TabbedPages is broken in the latest Prism released version (8.0.0.1909).
[Bug] Navigation when in Tabbed Pages doesn't change currently selected tab #2218
(It seems they finally have fixed this issue but they haven't released a new version until now)
So downgrade Prism.DryIoc to 7.2.0.1422 or wait for the next Prism release...
I have a collection view of images in my Xamarin Forms Project. I want to add onClick event on images to navigate to the respective page of each image. I tried to find the solution and there is no definite answer for it.
You could add a TapGestureRecognizer on Image .
in xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="xxx"
x:Name="CurrentPage" //set name here >
<CollectionView ItemsSource="{Binding Monkeys}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<Image
Source="{Binding xxx}"
Aspect="AspectFill"
HeightRequest="xxx"
WidthRequest="xxx" >
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference CurrentPage}, Path=BindingContext.ClickCommand}" />
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
in ViewModel
public ICommand ClickCommand { get; private set; }
INavigation Navigation;
public xxxViewModel(INavigation navigation)
{
Navigation = navigation;
ClickCommand = new Command(() => {
// navigation.PushAsync(xxx);
});
}
in ContentPage
public xxxPage()
{
InitializeComponent();
BindingContext = new xxxViewModel(this.Navigation);
}
I just created empty xamarin.forms project and nothing in it.
I searched on how to add Toolbar, in Microsoft documentation say add these line to xaml file.
<ContentPage.ToolbarItems>
<ToolbarItem Text="Example Item"
IconImageSource="example_icon.png"
Order="Primary"
Priority="0" />
</ContentPage.ToolbarItems>
But not toolbar is showing on my android device, this is really sad because this is my first time using xamarin and this is just empty project but it is not working.
this is my main xaml file
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="test3.MainPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="sssssssss Item"
Order="Primary"
Priority="0" />
</ContentPage.ToolbarItems>
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Your App.xaml.cs should be similar to this:-
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new test3.MainPage());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
I have a FlowListView control that is not displaying the items from a list. For test purposes I just wanted to display file path of the photo as a label.
Here is the xaml code:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms.Controls"
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
x:Class="TamarianApp.ImagePage">
<ContentPage.Content>
<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="true" x:Name="image_gallary" ItemsSource="{Binding photos}" HeightRequest="100" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Label Text="{Binding filepath}" TextColor="Black" Margin="20" VerticalOptions="Fill" HorizontalOptions="Fill" XAlign="Center" YAlign="Center"></Label>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
</ContentPage.Content>
</ContentPage>
Here is the backend:
public partial class ImagePage : ContentPage
{
public List<Photo> photos = App.rug.photos
public ImagePage()
{
InitializeComponent();
Title = "Photos";
}
}
'App.rug.photos' is a List of the Photo class which contains the string field 'filepath'. Debugging shows field 'photos' is not empty and contains the data from 'App.rug.photos.'
Please Help.
It may be to do with how you are assigning the list, you need to make sure that the list is a Property in order for the binding to work correctly.
Try..
public partial class ImagePage : ContentPage
{
public List<Photo> photos {get; set;}
public ImagePage()
{
InitializeComponent();
Title = "Photos";
photos = App.rug.photos
}
}
You may also need to set the binding context
public partial class ImagePage : ContentPage
{
public List<Photo> photos {get; set;};
public ImagePage()
{
InitializeComponent();
this.BindingContext = this;
Title = "Photos";
photos = App.rug.photos
}
}
Try this code.
public ObservableCollection<object>() photos;
...
var oc = new ObservableCollection<Photo>();
foreach (var item in App.rug.photos)
oc.Add(item);
photos = oc as ObservableCollection<object>;
I was having trouble with ObservableCollection<MyObject>, but solved it by using ObservableCollection<object>.