This is the xaml for the app I'm working on. It simply displays a map on the screen with a ListView:
<?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:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:GasStations"
x:Class="GasStations.MainPage">
<StackLayout>
<StackLayout VerticalOptions="FillAndExpand">
<maps:Map WidthRequest="960" HeightRequest="200"
x:Name="MyMap"
IsShowingUser="true"/>
<ListView x:Name="ListView_Pets">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>dog</x:String>
<x:String>cat</x:String>
<x:String>bird</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</StackLayout>
</ContentPage>
I set the property Map.IsShowingUser="true" thinking that it would display the current location, but it's not showing the point.
This is what the form looks like. It doesn't display the current location pin.
My question is: how can I add current location to the map?
Use the Geolocation plugin to get your current location. If you don't have it already and then use the MoveCamera method to move to that position:
private async Task TrackCurrentLocation()
{
var current = await CrossGeolocator.Current.GetPositionAsync();
current.Accuracy = 30;
float bearing =//bearing in case any
var pins = new Pin { Label = "ME", Icon =''yourIcon"), Flat = true
};
var latitude = current.Latitude;
var longitude = current.Longitude;
Device.BeginInvokeOnMainThread(() =>
{
pins.Position = new Position(latitude, longitude);
pins.Rotation = bearing;
if (MapTrack.Pins.Count == 0)
{
MapTrack.Pins.Add(pins);
}
else
{
MapTrack.Pins[0] = pins;
}
MapTrack.MoveCamera(CameraUpdateFactory.NewPosition(new Position(latitude, longitude)));
});
}
Related
I have a ContentPage that is bound to a viewmodel. Still, at one point, I need to access a Picker inside a StackLayout which in turn is in a Syncfusion ListViewItem. The XAML is pretty straightforward:
<?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" xmlns:sf="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
mc:Ignorable="d"
x:Class="PerformanceTM.Views.NewCircuitView">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<sf:SfListView x:Name="ExerciseList" ItemsSource="{Binding Exercises}" DragStartMode="OnHold">
<sf:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Picker Title="Kategorie" x:Name="CategoryPicker" ItemsSource="{Binding Source={x:Reference ExerciseList}, Path=BindingContext.ExerciseCategories}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding Category}" SelectedIndexChanged="CategoryChanged"/>
<Picker Title="Übung" x:Name="ExerciseNamePicker" ItemDisplayBinding="{Binding Name}" SelectedIndexChanged="ExerciseSelected"/>
<Button Text="..." Clicked="ConfigureSetsClicked"/>
<Button Text="(-)" />
</StackLayout>
</ViewCell>
</DataTemplate>
</sf:SfListView.ItemTemplate>
</sf:SfListView>
<StackLayout Orientation="Horizontal">
<Button Text="(+) Übung" Command="{Binding AddExerciseCommand}"/>
<Button Text="Ok" Command="{Binding ApplyChangesCommand}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
As you can see, both Pickers in the ViewCell have x:Name assigned to them. When I select a value in the ExerciseCategoryPicker, I load and assign new values to to ExerciseNamePicker in Code behind, like so:
private async void CategoryChanged(object sender, EventArgs e)
{
var picker = sender as Picker;
var stackLayout = picker.Parent as StackLayout;
ListViewItem listViewItem = stackLayout.Parent as ListViewItem;
var ex = picker.BindingContext as Exercise;
if (ex is null)
return;
ex.Category = picker.SelectedItem as ExerciseCategory;
var apiService = new ApiServices();
var exsForCategory = await apiService.GetExercisesForCategory(ex.Category.Name);
Picker exnp = stackLayout.FindByName<Picker>("ExerciseNamePicker");
if (exnp is null)
exnp = stackLayout.Children.OfType<Picker>().Where(x => x.Title == "Übung").FirstOrDefault();
exnp.ItemsSource = exsForCategory;
if (exsForCategory.Count > 0)
exnp.SelectedItem = exsForCategory.FirstOrDefault();
var bc = this.BindingContext as NewCircuitViewModel;
bc.ExercisePairing.Descriptor = bc.ExercisePairing.UpdateDescriptor();
}
private void ExerciseSelected(object sender, EventArgs e)
{
try
{
var picker = (sender as Picker);
var stackLayout = picker.Parent as StackLayout;
var vc = picker.Parent.Parent as Syncfusion.ListView.XForms.ListViewItem;
var ex = vc.BindingContext as Exercise;
var se = picker.ItemsSource[picker.SelectedIndex] as Exercise;
var exnp = stackLayout.FindByName("CategoryPicker") as Picker;
if (exnp is null)
exnp = stackLayout.Children.OfType<Picker>().Where(x => x.Title == "Kategorie").FirstOrDefault();
var ec = exnp.SelectedItem as ExerciseCategory;
ex.Category = ec;
ex.Name = se.Name;
ex.Id = se.Id;
ex.Description = se.Description;
ex.VideoUrl = se.VideoUrl;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Now what happens is that FindByName() returns null in each situation. Oddly enough, when I debug and inspect the Children of StackLayout just before calling FindByName, it does contain children with the appropriate IDs (i.e., the x:Name). When I access them via get, I get the GUID (this somehow confuses me, as I thought there should only be a GUID in the first place, but well).
I have found a workaround by just selecting the element by Title, but this is a rather strange behaviour, especially considering that this has worked in the past. Only change I made since then was the integration of the SyncFusion ListView. Could that be an issue? Has anyone experienced this and/or can provide more insight?
PS: I have gone through all the "usual" fixes such as deleting the .v, bin and obj folders...
You can get the children element of SfListView.ItemTemplate using behavior for the parent element of the ItemTemplate. Please refer the following code snippet for getting the named elements inside DataTemplate,
Xaml: Define Behavior for StackLayout
<sf:SfListView x:Name="ExerciseList" ItemsSource="{Binding Exercises}" DragStartMode="OnHold">
<sf:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<StackLayout.Behaviors>
<local:Behavior/>
</StackLayout.Behaviors>
<Picker Title="Kategorie" x:Name="CategoryPicker" ItemsSource="{Binding Source={x:Reference ExerciseList}, Path=BindingContext.ExerciseCategories}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding Category}"/>
<Picker Title="Übung" x:Name="ExerciseNamePicker" ItemDisplayBinding="{Binding Name}"/>
<Button Text="..." Clicked="ConfigureSetsClicked"/>
<Button Text="(-)" />
</StackLayout>
</ViewCell>
</DataTemplate>
</sf:SfListView.ItemTemplate>
Behavior: Get element using FindByElement. Trigger SelectedIndexChanged event for Picker.
public class Behavior : Behavior<StackLayout>
{
Picker CategoryPicker;
Picker ExerciseNamePicker;
protected override void OnAttachedTo(StackLayout bindable)
{
CategoryPicker = bindable.FindByName<Picker>("CategoryPicker");
ExerciseNamePicker = bindable.FindByName<Picker>("ExerciseNamePicker");
CategoryPicker.SelectedIndexChanged += CategoryPicker_SelectedIndexChanged;
ExerciseNamePicker.SelectedIndexChanged += ExerciseNamePicker_SelectedIndexChanged;
base.OnAttachedTo(bindable);
}
private void ExerciseNamePicker_SelectedIndexChanged(object sender, EventArgs e)
{
//Your logic here.
}
private void CategoryPicker_SelectedIndexChanged(object sender, EventArgs e)
{
//Your logic here.
}
}
You can also refer our online document regarding the same from the following link,
Document
I used MasterDetailPage. And navigation with NavigationPage.
This simple is good work before add in project CarouselView.
public List<MasterPageItem> menuList { get; set; }
public MainPage()
{
InitializeComponent();
menuList = new List<MasterPageItem>();
menuList.Add(new MasterPageItem() { Title = "Главная", Icon = "home.png", TagetType = typeof(HomePage) });
menuList.Add(new MasterPageItem() { Title = "Расписание", Icon = "calendar.png", TagetType = typeof(DiaryPage) });
menuList.Add(new MasterPageItem() { Title = "Новости", Icon = "news.png", TagetType = typeof(NewsPage) });
menuList.Add(new MasterPageItem() { Title = "Профиль", Icon = "profile.png", TagetType = typeof(ProfilePage) });
navigationDrawerList.ItemsSource = menuList;
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(TestPage)));
}
private void onMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (MasterPageItem)e.SelectedItem;
Type page = item.TagetType;
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsPresented = false;
}
if open page include CarouselView and property VerticalOptions="FillAndExpand" then visible exception
System.NotSupportedException: Unable to activate instance of type Com.ViewPagerIndicator.CirclePageIndicator
from native handle 0x7fc5472274 (key_handle 0x584e8e5).
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:carousel="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
x:Class="AppMobile.Views.HomePage"
Title="Home">
<ContentPage.Content>
<StackLayout>
<StackLayout HeightRequest="300">
<carousel:CarouselViewControl x:Name="MyCV" BackgroundColor="Green" VerticalOptions="FillAndExpand" >
<!--ShowIndicators="True" -->
<carousel:CarouselViewControl.ItemTemplate>
<DataTemplate>
<StackLayout BackgroundColor="Blue">
<Image x:Name="myImg" Source="{Binding FileName}" Aspect="AspectFill" />
</StackLayout>
</DataTemplate>
</carousel:CarouselViewControl.ItemTemplate>
</carousel:CarouselViewControl>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
if exclude property VerticalOptions="FillAndExpand" then content in CarouselViewControl is empty. Why use both component with out error?
I'm having a problem with the PanGestuer behaviour in Xamarin Form. This is my 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:Xamarin_Test"
x:Class="Xamarin_Test.MainPage">
<StackLayout x:Name="parentFrame" Margin="100" BackgroundColor="Gray">
<AbsoluteLayout x:Name="parentLayout" BackgroundColor="Red">
<local:PanContainer x:Name="parentContainer" BackgroundColor="Yellow">
<Image x:Name="panImage" Source="MonoMonkey.jpg"
WidthRequest="{Binding Path=Width, Source={x:Reference Name=parentFrame}}"
HeightRequest="{Binding Path=Height, Source={x:Reference Name=parentFrame}}"/>
</local:PanContainer>
</AbsoluteLayout>
</StackLayout>
</ContentPage>
PanContainer.cs
public class PanContainer : ContentView
{
double x, y;
public PanContainer()
{
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(panGesture);
}
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
Content.TranslationX = Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - App.ScreenWidth));
Content.TranslationY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - App.ScreenHeight));
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
break;
}
}
}
The image loads with correct size (within the StackLayout borders, for better testing I colorized the elements). The panning works to the left and to the upper way of the image, but overlays the white area. How can I handle panning, so that the moved image is only visible within my panContainer?
I have page in XAML and need it in pure C#. But can't figure out how to convert it.
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="xmr_cross_test.Navigation.MDPage">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Orientation="Vertical">
<ListView x:Name="navigationDrawerList"
RowHeight="60"
SeparatorVisibility="None"
ItemSelected="OnMenuItemSelected">
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
How to do so keeping binding and ability to change MasterDetailPage.Detail?
I had to remove ListView.ItemTemplate declaration as SO doesn't allow me to post so big amount of code. Guess it won't be too hard to figure out after I get answer.
MasterDetailPage mdp = new MasterDetailPage();
ContentPage master = new ContentPage { Title = "Menu" };
StackLayout menu = new StackLayout();
ListView menuList = new ListView() { RowHeight = 60 };
menuList.ItemSelected += OnMenuItemSelected;
ContentPage detail = new ContentPage();
menu.Children.Add(menuList);
master.Content = menu;
mdp.Master = master;
mdp.Detail = new NavigationPage(detail);
I am developing an app using Xamarin, and currently trying to display the screen width to the (I later plan to base sizes of certain objects off this)
I am attempting to use bindings to do this, but unfortunately it doesn't appear to work as expected. It does not throw an exception, just the label that I am attempting to bind has no text value.
I am sure I will be using bindings quite a lot during the rest of the project, so I would be greatly appreciative of any advice.
Please consider the following code:
C#:
using Xamarin.Forms;
using XLabs.Ioc;
using XLabs.Platform.Device;
namespace TimerStyles
{
public partial class SavedTimesPage : ContentPage
{
string screenWidthText = "";
public SavedTimesPage()
{
InitializeComponent();
this.screenWidth = getScreenWidth();
}
public string screenWidth
{
protected set
{
screenWidthText = value;
}
get { return screenWidthText; }
}
public string getScreenWidth()
{
var dev = Resolver.Resolve<IDevice>();
var display = dev.Display;
double ScreenWidthInches = (double)display.Width / display.Xdpi;
var ScreenWidth = (ScreenWidthInches.ToString());
return ScreenWidth;
}
public string getScreenHeight()
{
var dev = Resolver.Resolve<IDevice>();
var display = dev.Display;
double ScreenHeightInches = (double)display.Height / display.Ydpi;
var ScreenHeight = (ScreenHeightInches.ToString());
return ScreenHeight;
}
}
}
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:TimerStyles="clr-namespace:TimerStyles;assembly=TimerStyles"
x:Class="TimerStyles.SavedTimesPage"
NavigationPage.HasNavigationBar="false">
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="#232224">
<Label Text="x" TextColor="Blue" FontSize="Large"/>
<Label Text="{Binding screenWidth}" TextColor="Blue" FontSize="Large"/>
<Label Text="x" TextColor="Blue" FontSize="Large"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
This was solved by creating a "view-model" class to act as an intermediary between the view and the model, as per the following link:
https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/
(Obtained by following further on the link given in comments by cristallo)
Hopefully this will help anyone in the space-age future with the same issue.