I have a simple screen example trying to implement the ScrollToAsync function. I can't get the function to scroll at all.
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"
x:Class="MyApp.ItemList">
<ContentPage.Content>
<ScrollView x:Name="myScroll">
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!" />
<Label Text="Welcome to Xamarin.Forms!" />
<Label Text="Welcome to Xamarin.Forms!" />
<Label Text="Welcome to Xamarin.Forms!" />
// Many labels to fill space here
<Label Text="Welcome to Xamarin.Forms!" />
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
And the C# is:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ItemList : ContentPage
{
public ItemList ()
{
InitializeComponent ();
myScroll.ScrollToAsync(0, 100, false);
}
}
What am I doing wrong? It must be something simple I need to do. I already tried wrapping the ScrollToAsync call in an async method, so I can use "await" before it, but this did not work.
That is because the scroll is not loaded yet, better try to add this method to your code
protected override void OnAppearing()
{
base.OnAppearing();
scLista.ScrollToAsync(0,100,false);
}
Adding Delay would helped You ,
I set it in a timer and worked fine for me .
public MainPage()
{
InitializeComponent();
StarAnimate();
}
private void StarAnimate()
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
myScroll.ScrollToAsync(LatestElment, ScrollToPosition.Center, true);
return false;
});
}
LatestElment:The element to scroll.
Related
I want to create an application that can Create, Read, Update and Delete Merchandiser records.
I am struggling with how to "Update" and "Delete" a record based on a ItemSelected in the ListView.
The item selected in the ListView represents a Merchandiser and is currently being passed into each new View as an argument.
I intend to store data in an SQLite database, but for simplicity have not included any of that logic. Database Commands (Save, Delete etc.) will be created in the MerchandiserViewModel
Here is my slimmed down code so far
Merchandiser.cs Model
public class Merchandiser
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
// Additional Properties not shown for simplicity
}
MerchandiserViewModel.cs ViewModel
public class MerchandiserViewModel : ViewModelBase
{
public ObservableCollection<Merchandiser> MerchandiserList { get; set; }
private Merchandiser selectedItem;
public Merchandiser SelectedItem
{
get { return selectedItem; }
set
{
selectedItem = value;
RaisePropertyChanged();
}
}
public MerchandiserViewModel()
{
MerchandiserList = new ObservableCollection<Merchandiser>();
CreateData();
}
private void CreateData()
{
for (int i = 0; i < 20; i++)
{
Merchandiser merchandiser = new Merchandiser();
merchandiser.Name = $"Merchandiser {i}";
merchandiser.PhoneNumber = $"12{i}6{i*3}{i*8}{i*9/3+2}";
MerchandiserList.Add(merchandiser);
}
}
}
// Database commands and other logic not shown...
}
BaseViewModel.cs
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MerchandiserListPage.xaml & .cs View - Display List of Merchandiers
<?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="MVVM.Views.MerchandisersListPage">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="MerchandiserListView"
ItemSelected="MerchandiserListView_ItemSelected"
SelectionMode="Single"
HasUnevenRows="True"
ItemsSource="{Binding MerchandiserList}"
SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label
FontSize="Large"
Text="{Binding Name}"
VerticalOptions="Center" />
<Label
FontSize="Small"
Text="{Binding PhoneNumber}"
VerticalOptions="Center" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
// MerchandisersListPage.xaml.cs - Code Behind
public MerchandisersListPage()
{
InitializeComponent();
this.BindingContext = new MerchandiserViewModel();
}
private async void MerchandiserListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
Merchandiser merchandiser = (Merchandiser)e.SelectedItem;
await Navigation.PushAsync(new MerchandisersProfilePage(merchandiser));
}
MerchandisersProfilePage.xaml & .cs
This page should navigate to the MerchandiserEditPage using an Edit Button but I'm not sure if I am handling the 'Code Behind' correctly?
<?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="MVVM.Views.MerchandisersProfilePage">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Name: " />
<Label
FontSize="Large"
Text="{Binding Name}"
VerticalOptions="Center" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="PhoneNumber: " />
<Label
FontSize="Small"
Text="{Binding PhoneNumber}"
VerticalOptions="Center" />
</StackLayout>
<Button Text="Edit"
Clicked="EditButton_Clicked"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
// MerchandisersProfilePage.xaml.cs - Code Behind
Merchandiser selectedMerchandiser;
public MerchandisersProfilePage(Merchandiser merchandiser)
{
InitializeComponent();
selectedMerchandiser = merchandiser; // Is this what I should be doing?
this.BindingContext = merchandiser;
}
private async void EditButton_Clicked(object sender, EventArgs e)
{
// Am I doing this the correct way??
await Navigation.PushAsync(new MerchandiserEditPage(selectedMerchandiser));
}
MerchandiserEditPage.xaml & .cs This is where I am stuck.
I will need to update the record in the database by calling a method in the MerchandiserViewModel but am not sure how to do this? The method (which ideally should be called by a Command) to update the database has the following signature UpdateMerchandiser(Merchandiser merchandiser).
Ideally I would like the Save Button to use a Command instead of Clicked so I can access the Save command in the MerchandiserViewModel but this imposes another problem around form validation. How then can I then validate this information (e.g. Name is not empty) before saving it the the database? Because the MerchandiserViewModel doesn't know anything about the MerchandiserEditPage.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"
x:Class="MVVM.Views.MerchandiserEditPage">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Name: " />
<Entry
FontSize="Large"
Text="{Binding Name}"
VerticalOptions="Center" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="PhoneNumber: " />
<Entry
FontSize="Small"
Text="{Binding PhoneNumber}"
VerticalOptions="Center" />
</StackLayout>
<!-- Ideally this should use 'Command' instead of 'Clicked' -->
<Button Text="Save"
Clicked="SaveButton_Clicked"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
// MerchandiserEditPage.xaml.cs - Code Behind
public MerchandiserEditPage(Merchandiser merchandiser)
{
InitializeComponent();
this.BindingContext = merchandiser;
}
// I would prefer not to use an event handler but use a Command in the MerchandiserViewModel instead
// I also need to perform some basic validation e.g. Name entry should not be empty etc.
private async void SaveButton_Clicked(object sender, EventArgs e)
{
// How can I Save/Update the changes?
// Pop() page off the stack and return to the MerchandiserProfileView
await Navigation.PopAsync();
}
I believe the above code is designed in accordance to MVVM, however if not, please advise where I am violating this pattern?
I also want to do similar for deleting a record but once I get the update method sorted I'm sure deleting will follow similar logic.
Note: The code above is not shown in its entirety and is missing SQLite database functionality and other logic for simplicity. All functionality to the database (Save, Update, Delete) is in the MerchandiserViewModel. I will edit or add any additional information to this question as required to help provide a complete picture of the problem.
I'm using the AnimationNavigationPage nuget package (found here) to try and create a page slide animation going from right to left. So far it seems that all I'm able to get is left to right and it doesn't reflect when I change the animation type / subtype.
I'm sure I'm just missing something small but for the life of me I can't see it.
MainPage.xaml.cs
using FormsControls.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace PageNavigationExample
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : AnimationPage
{
public MainPage()
{
InitializeComponent();
}
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new Page1());
}
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<controls:AnimationPage
xmlns:controls="clr-namespace:FormsControls.Base;assembly=FormsControls.Base" 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="PageNavigationExample.MainPage">
<controls:AnimationPage.PageAnimation>
<controls:SlidePageAnimation Duration="Short" Type="Slide" Subtype="FromRight"/>
</controls:AnimationPage.PageAnimation>
<StackLayout>
<!-- Place new controls here -->
<Label Text="Main page"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Main page button"
Clicked="Button_Clicked"/>
</StackLayout>
</controls:AnimationPage>
And then just basic content pages for navigation purposes that I haven't modified...Page1, Page2, etc.
What am I missing here to just get the slide animation to slide in from the right when I click a button and slide in from the left when I click the Back button?
And then just basic content pages for navigation purposes that I
haven't modified...Page1, Page2, etc.
Have you let your Page1, Page2, etc to inherit AnimationPage and set the PageAnimation?
for example:
app.xaml.cs :
public App()
{
InitializeComponent();
MainPage = new AnimationNavigationPage(new MainPage());
}
MainPage.xaml.cs:
public partial class MainPage : AnimationPage
{
public MainPage()
{
InitializeComponent();
}
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new Page1());
}
}
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<controls:AnimationPage 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"
xmlns:controls="clr-namespace:FormsControls.Base;assembly=FormsControls.Base"
x:Class="App18.MainPage">
<controls:AnimationPage.PageAnimation>
<controls:SlidePageAnimation Duration="Medium" Subtype="FromRight" />
</controls:AnimationPage.PageAnimation>
<StackLayout>
<!-- Place new controls here -->
<Label Text="Main page"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Main page button"
Clicked="Button_Clicked"/>
</StackLayout>
</controls:AnimationPage>
Page1.xaml.cs:
public partial class Page1: AnimationPage
{
public Anim2()
{
InitializeComponent();
}
}
Page1.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<controls:AnimationPage 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"
xmlns:controls="clr-namespace:FormsControls.Base;assembly=FormsControls.Base"
x:Class="App18.Page1">
<controls:AnimationPage.PageAnimation>
<controls:SlidePageAnimation Duration="Short" Type="Slide" Subtype="FromRight"/>
</controls:AnimationPage.PageAnimation>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</controls:AnimationPage>
the effect like:
In Xamarin.Forms I would like to bind a code behind property to a label in XAML.
I found many answers and web pages about this topic, but they all cover more complex scenarios.
This is my XAML page:
<?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:local="clr-namespace:TrackValigie"
x:Class="TrackValigie.SelViaggioPage">
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding ?????????}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
And this is code behind:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SelViaggioPage : ContentPage
{
private string _lblText;
public string LblText
{
get
{
return _lblText;
}
set
{
_lblText = value;
OnPropertyChanged();
}
}
public SelViaggioPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
this.LblText = "Ciao!!";
base.OnAppearing();
}
}
I would like to bind the "LblText" property to the label, using XAML only, that means without setting binding or binding context in code behind.
Is this possible?
your page will need to implement INotifyPropertyChanged, but the binding syntax should just be
<ContentPage x:Name="MyPage" ... />
...
<Label BindingContext="{x:Reference Name=MyPage}" Text="{Binding LblText}" />
Or if you don't want to swap the binding context for the entire control then use the 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:Name="this"
x:Class="SomePage">
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding SomeProp, Source={x:Reference this}}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Just add BindingContext = this; in code behind file.
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:local="clr-namespace:TrackValigie"
x:Class="TrackValigie.SelViaggioPage">
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding LblText}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Code Behind
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SelViaggioPage : ContentPage
{
private string _lblText;
public string LblText
{
get
{
return _lblText;
}
set
{
_lblText = value;
OnPropertyChanged();
}
}
public SelViaggioPage()
{
InitializeComponent();
BindingContext = this;
}
protected override void OnAppearing()
{
base.OnAppearing();
this.LblText = "Ciao!!";
}
}
You need to set the x:Name for ContentPage as mentioned by Jason's Answer .
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TrackValigie"
x:Class="TrackValigie.SelViaggioPage"
x:Name = "MyControl"/>
Instead of using BindingContext, you can use ElementName
<TextBlock Text="{Binding ElementName=TestControl,Path=StudentName}"/>
I am trying to create simple multi-screen App.
I added Content Page and button to it.
MapPage.xaml.cs:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MapPage : ContentPage
{
public MapPage ()
{
InitializeComponent ();
}
void ShowMap(object s, EventArgs e)
{
}
}
MapPage.xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App14"
x:Class="App14.MapPage">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin Forms!" />
<Button Text="show map"
Clicked="ShowMap"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I am getting error: ShowMap Method does not have correct signature
What I am doing wrong?
change the event handler from private (the default if not specified) to protected
protected void ShowMap(object s, EventArgs e)
{
}
I cant find a way to implement an onClick event on a button that will allow the application to navigate between the login and the second view.
How can I do that ?
Here is what i did
I created a method in my LoginViewModel.cs file that should redirect me to the second view.
class LoginViewModel
{
private async Task SecondView_Click()
{
App.Current.MainPage = new NavigationPage(new SecondView());
}
}
Then I've defined a BindingContext in my Login.cs
public partial class Login : ContentPage
{
public Login()
{
InitializeComponent();
BindingContext = new LoginViewModel();
}
}
Then I define a button in my Login.xaml that has a binded command property
<StackLayout
VerticalOptions="CenterAndExpand">
<Entry StyleId="UsernameEntry"
Placeholder="Username"
Text="{Binding Username}" />
<Entry StyleId="PasswordEntry"
Placeholder="password"
Text="{Binding Password}" />
<Button
StyleId="btn_connexion"
Text="Connexion"
Command="{Binding connexion}" />
<Button
StyleId="btn_testSecondView"
Text="Test 2nd View"
Command="{Binding SecondView_Click}"></Button>
</StackLayout>
This works for me
PAGE 1 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"
x:Class="TestRelativeLayout.MyPage1"
Title="TabbedPage">
<StackLayout>
<Button Clicked="Handle_Clicked" Text = "Press">
</Button>
</StackLayout>
</ContentPage>
PAGE 1 XAML.CS
using Xamarin.Forms;
namespace TestRelativeLayout
{
public partial class MyPage1 : ContentPage
{
public MyPage1()
{
InitializeComponent();
}
public void Handle_Clicked(object sender, System.EventArgs e)
{
Application.Current.MainPage = new NavigationPage(new MyPage2());
}
}
}
Try to remove
private async Task
and use
void
private async Task SecondView_Click()
{
App.Current.MainPage = new NavigationPage(new SecondView());
}
Here is what I did.
I found that there is a "clicked" property on that prompt an intellisense dropdown with a "new event handler".
<StackLayout
VerticalOptions="CenterAndExpand">
<Entry StyleId="UsernameEntry"
Placeholder="Username"
Text="{Binding Username}" />
<Entry StyleId="PasswordEntry"
Placeholder="password"
Text="{Binding Password}" />
<Button
StyleId="btn_connexion"
Text="Connexion"
Clicked="connexion" />
<Button
StyleId="btn_testSecondView"
Text="Test 2nd View"
Clicked="SecondView_Click"></Button>
</StackLayout>
Once i did that it created a method in the code behind "Login.xaml.cs".
From there I just paste the navigation method and it worked
private async Task SecondView_Click()
{
App.Current.MainPage = new NavigationPage(new SecondView());
}
The fact that it is a PCL project makes it difficult to find the right information because everything you find on the internet concerns the ios/android solution and not the portable solution.