СarouselView does not display content - xamarin

СarouselView does not display content. I have the following code in the AppShell.axml
for the whole day I can’t figure out how to make this work. Help make a working code.
<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"
xmlns:local="clr-namespace:test.Views"
BackgroundColor="Azure"
x:Class="test.AppShell">
<CarouselView HorizontalOptions="Center" NumberOfSideItems="1">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="20"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="11111111111"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentPage>
I have the following code in the AppShell.axml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace test
{
public partial class AppShell : ContentPage
{
public AppShell()
{
InitializeComponent();
}
}
}
I tried such an example and it works, but I need the option to work from above.
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</CarouselView.ItemsSource>
</CarouselView>

Firstly why you place a carsouselView in the Appshell.xaml? I think the AppShell.Xaml is only to set the App configurations.
you can write code in the AppShell.xaml to layout the App menu or flylayout.
if you do not specify a ItemsSource to CarouselView It will not renderer.
you can make the ItemsSource by BindingContext.

Do you want to achieve the result like following GIF?
If so, you could show the content in the CarouselView by DataBinding.
Step 1: Create a Model for your CarouselView, I create it like following code.
public class MyModel
{
public string Name { get; set; }
}
Step 2: create a viewModel for your CarouselView(we can add the content that we want them to display).
public class MyModelView: BaseViewModel
{
public ObservableCollection<MyModel> MyModels { get; set; }
public MyModelView()
{
MyModels = new ObservableCollection<MyModel>();
MyModels.Add(new MyModel() { Name="test1"});
MyModels.Add(new MyModel() { Name = "test2" });
MyModels.Add(new MyModel() { Name = "test3" });
MyModels.Add(new MyModel() { Name = "test4" });
MyModels.Add(new MyModel() { Name = "test5" });
MyModels.Add(new MyModel() { Name = "test6" });
}
}
Step 3: please add the ItemsSource for your CarouselView and binding the properties for xamarin forms control(Label)
<CarouselView HorizontalOptions="Center" NumberOfSideItems="1" ItemsSource="{ Binding MyModels}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="20"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
Step 4: backend code for your CarouselView.To bind your ModelView for layout.
BindingContext = new MyModelView();
Here is an example project. you can refer to it.
https://github.com/851265601/MyShellCarouselView

Related

Xamarin reuse viewmodel on user control

In my MainPage.xaml, which is a ContentPage, I have two user controls.
Both of which are ContentView and are loaded like this:
<local:MyView2 HorizontalOptions="Start"
VerticalOptions="Fill">
<local:MyView2.BindingContext>
<viewmodels:NavbarViewModel />
</local:MyView2.BindingContext>
<local:MyView2.Triggers>
<DataTrigger TargetType="{x:Type local:MyView2}" Binding="{Binding IsPresented}" Value="True">
<DataTrigger.EnterActions>
<local:MenuTrigger IsPresented="True"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<local:MenuTrigger IsPresented="False" />
</DataTrigger.ExitActions>
</DataTrigger>
</local:MyView2.Triggers>
</local:MyView2>
// omitted myview1, they are basically the same
My MainPage has a different viewmodel than MyView1 and 2 which are the contentviews.
But the bindingcontext I have said is not accessible from inside the contentview:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Universal_ONE.MyView1"
x:Name="MyView1Name">
<Frame BackgroundColor="#385C6C"
Padding="0,0,0,0">
<ImageButton Source="outline_menu_white_24.png"
Command="{Binding Source={x:Reference MyView1Name}, Path=PresentMenu}}"
WidthRequest="24"
HeightRequest="24"
Margin="15,0,0,0"
BackgroundColor="Transparent"
HorizontalOptions="StartAndExpand" />
</Frame>
</ContentView>
I also tried it like this:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Universal_ONE.MyView1">
<Frame BackgroundColor="#385C6C"
Padding="0,0,0,0">
<ImageButton Source="outline_menu_white_24.png"
Command="{Binding PresentMenu}"
WidthRequest="24"
HeightRequest="24"
Margin="15,0,0,0"
BackgroundColor="Transparent"
HorizontalOptions="StartAndExpand" />
</Frame>
</ContentView>
The error I get on the PresentMenu: No DataContext found for binding PresentMenu
How do I access the bindingcontext inside my contentview?
If it was not clear already, the contentviews are in a seperate file.
EDIT:
NavbarViewModel:
public class NavbarViewModel : INotifyPropertyChanged
{
public NavbarViewModel()
{
isPresented = false;
PresentMenu = new Command(() => IsPresented = !IsPresented);
}
bool isPresented;
public bool IsPresented
{
get => isPresented;
set
{
isPresented = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsPresented)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ICommand PresentMenu { private set; get; }
}
EDIT 2:
I have added:
x:DataType="viewmodels:NavbarViewModel
To both contentviews, this removes the error that it has no DataContext. However, the binding still does not work.
Working solution:
I have now added the viewmodel as a staticresource in app.xaml and just reuse that everywhere including in the user controls. I hope to look at this again at some point in the future.

Any idea how to add CarouselView indicators inside the CarouselView it self?

I am using a CarouselView to display a few views
each one of them is basically 2 StackLayouts
like so
what I have done so far is create a CarouselView with a template for both of these Stacklayouts
<CarouselView
x:Name="MyCarouselView"
IsVisible="{Binding ShouldShow}"
ItemsSource="{Binding MyItemSource}"
Scrolled="CarouselView_Scrolled">
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView>
<FlexLayout Direction="Column" JustifyContent="SpaceBetween">
<StackLayout FlexLayout.Basis="25%">
<elements:TopView Data="{Binding}"/>
</StackLayout>
<StackLayout FlexLayout.Basis="75%">
<elements:BottomView Data="{Binding}"/>
</StackLayout>
</FlexLayout>
</ContentView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
Note: the views bind to different values but for simplicity sake, I wrote a simpler DataTemplate here.
it works fine and there is no problem in binding or anything
what I am trying to do is add indicators to show the user that there are more items and which one he is seeing now. (small circles or something like that).
the thing is I want to display them between the two views like so
Any idea of how to do it?
Any other way to achieve the wanted result is welcome as well
Please and thank you.
The easy way to implement that is using Grid to do that :
<Grid>
<!-- Place new controls here -->
<CarouselView x:Name="CustomCarouselView"
IndicatorView="indicatorView"
VerticalOptions="FillAndExpand"
>
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<ContentView BackgroundColor="LightBlue" >
<Label Text="{Binding TopViewTitle}" FontSize="Header" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HeightRequest="250"/>
</ContentView>
<ContentView BackgroundColor="LightGray" Margin="0,80,0,0">
<Label Text="{Binding BottomViewTitle}" FontSize="Header" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HeightRequest="250" />
</ContentView>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
IndicatorsShape="Square"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
VerticalOptions="Center"
Margin="0,-150,0,0" />
</Grid>
Above is my sample xaml code ,only need to custom the Margin property of IndicatorView and bottom ContentView after binding ItemSource for CarouselView :
List<CarouselModel> carouselModels = new List<CarouselModel>();
carouselModels.Add(new CarouselModel { TopViewTitle = "first top", BottomViewTitle = "first bottom" });
carouselModels.Add(new CarouselModel { TopViewTitle = "second top", BottomViewTitle = "second bottom" });
carouselModels.Add(new CarouselModel { TopViewTitle = "third top", BottomViewTitle = "third bottom" });
CustomCarouselView.ItemsSource = carouselModels;
The effect shows as expected :
The another way you can use RelativeLayout to implement that :
<RelativeLayout>
<!-- Place new controls here -->
<CarouselView x:Name="CustomCarouselView"
IndicatorView="indicatorView"
>
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<ContentView BackgroundColor="LightBlue">
<Label Text="{Binding TopViewTitle}"
FontSize="Header"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
HeightRequest="250" />
</ContentView>
<ContentView BackgroundColor="LightGray"
Margin="0,80,0,0">
<Label Text="{Binding BottomViewTitle}"
FontSize="Header"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
HeightRequest="250" />
</ContentView>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
IndicatorsShape="Square"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=0.5,Constant=-25}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height,Factor=0.5,Constant=-75}"
/>
</RelativeLayout>
Here you can modify RelativeLayout.XConstraint and RelativeLayout.YConstraint of IndicatorView to set the space between two ContentView . The Margin property
of Bottom ContentView also need to set , it's effect is to show the space between two ConentView .
You can achieve this in two methods :-
Grid, where you can place both the controls in the same Grid.Row.
Assign VerticalOptions="FillAndExpand" to the CarouselView and VerticalOptions="Center" to the IndicatorView.
By Using AbsoluteLayout.
Let me know if you have more queries.
We can achieve this scenario by placing a carousel view inside the parent carousel view and providing the Indicator view for the carousel placed inside.
Also we need to bind the "Position" property of inside carousel view properly, so that indicator view points to the proper selected index. Please find the code below for reference,
Inside Xaml:
<StackLayout Padding="30">
<CarouselView x:Name="MyCarouselView"
ItemsSource="{Binding MyItemSource}"
FlowDirection="MatchParent">
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView>
<FlexLayout Direction="Column"
JustifyContent="SpaceBetween"
BackgroundColor="Pink">
<StackLayout FlexLayout.Basis="5%">
<BoxView HeightRequest="100"
WidthRequest="100"
BackgroundColor="{Binding Boxview1Color}" />
</StackLayout>
<CarouselView FlexLayout.Basis="0%"
IndicatorView="indicatorView"
IsSwipeEnabled="False"
ItemsSource="{Binding Items}"
Position="{Binding Position}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding ItemText}"/>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
FlexLayout.Basis="10%"
HeightRequest="10"
IndicatorsShape="Circle"
IndicatorColor="White"
SelectedIndicatorColor="DarkBlue">
</IndicatorView>
<StackLayout FlexLayout.Basis="60%">
<BoxView HeightRequest="100"
WidthRequest="100"
BackgroundColor="{Binding Boxview2Color}"/>
</StackLayout>
</FlexLayout>
</ContentView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
Inside ViewModel:
public class MainPageViewModel
{
private ObservableCollection<MyItemSourceViewModel> _myItemSource;
public ObservableCollection<MyItemSourceViewModel> MyItemSource { get; set; }
public MainPageViewModel()
{
MyItemSource = new ObservableCollection<MyItemSourceViewModel>();
MyItemSource.Add(new MyItemSourceViewModel { Boxview1Color = Color.Red, Boxview2Color = Color.Blue, Position = 0 });
MyItemSource.Add(new MyItemSourceViewModel { Boxview1Color = Color.Green, Boxview2Color = Color.Purple, Position = 1});
MyItemSource.Add(new MyItemSourceViewModel { Boxview1Color = Color.PeachPuff, Boxview2Color = Color.Brown, Position = 2 });
var count = MyItemSource.Count;
foreach(var item in MyItemSource)
{
var itemCount = count;
var i = 0;
item.Items = new List<ItemsModel>();
while(itemCount > 0)
{
var itemModel = new ItemsModel { ItemText = i.ToString()};
item.Items.Add(itemModel);
i++;
itemCount--;
}
}
}
}
public class MyItemSourceViewModel
{
public Color Boxview1Color { get; set; }
public Color Boxview2Color { get; set; }
public int Position { get; set; }
public List<ItemsModel> Items { get; set; }
}
public class ItemsModel
{
public string ItemText { get; set; }
}
Please refer below screenshots as well:
Sample screenshot 1
Sample screenshot 2

Xamarin.Forms GestureRecognizers not working on Command

Code in the xaml page:
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<CollectionView ItemsSource="{Binding MeniElementi}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame Padding="10" WidthRequest="140" HeightRequest="140">
<Frame BackgroundColor="AliceBlue" WidthRequest="120" HeightRequest="120" HasShadow="True" CornerRadius="10" Padding="10" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" >
<StackLayout>
<Image Source="http://www.clker.com/cliparts/l/u/5/P/D/A/arrow-50x50-md.png" WidthRequest="70" HeightRequest="70" >
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding LoadElements}"
/>
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding Title}" HeightRequest="50" WidthRequest="100" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</StackLayout>
</Frame>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
Code in xaml.cs:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Menu: ContentPage
{
MenuViewModel viewModel = new MenuViewModel();
public Menu()
{
InitializeComponent();
BindingContext = viewModel;
}
}
Code in viewmodel.cs
public class MenuViewModel :BaseViewModel, INotifyPropertyChanged
{
public Command LoadElements { get; set; }
public ObservableCollection<Meni> MeniElementi { get; set; }
public MenuViewModel()
{
LoadElements= new Command(execute: async () => await ExecuteElements());
MeniElementi = new ObservableCollection<Meni>() {
new Meni(){Title="Transatcions" ,Picture="xxx"},
new Meni(){Title="Transatcions" ,Picture="xxx"},
};
}
async Task ExecuteElements()
{
try
{
await Application.Current.MainPage.Navigation.PushAsync(new InfoPage());
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
}
}
LoadElements Command not fired. Loading starting menu , showing menu elements just command not working to navigate to another page. Using Xamarin.Forms.Command. On other pages working normal with Command
You could reset the binding path of the tap . So that you can handle the logic in the same command .
in the ContentPage (which contains the CollectionView)
<?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:Name="Page" //set the name of page
x:Class="xxx.xxxPage">
<TapGestureRecognizer Command="{Binding Source={x:Reference Page},Path=BindingContext.LoadElements}"
you need to call the command on the ViewModel of the Page for that you need to do this:-
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoadElements, Source={x:Reference Name=ThisPage}}" />
</Image.GestureRecognizers>
And put x:Name="ThisPage" in the ContentPage tag of the xaml at the top of the page.
Let me know if you face difficulties.

Binding Xamarin XAML to code behind properties (ListView)

I want to bind my code-behind property, which is a list, to a XAML ListView. However, my ListView is never populated and I have no idea why.
<?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="BLEPl.EvaluationPage"
Title="Evaluation">
<ContentPage.Content>
<StackLayout Padding="0,20,0,20">
<ListView HasUnevenRows="True" IsVisible="True" x:Name="TableLayout" ItemsSource="{Binding Path=SensorValues}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label Style="{StaticResource TitleLabel}" Grid.Column="0" Grid.Row="0" Text="Zeitstempel: " />
<Label Style="{StaticResource DataLabel}" Grid.Column="1" Grid.Row="0" Text="{Binding TimeStamp}" />
<Label Style="{StaticResource TitleLabel}" Grid.Column="0" Grid.Row="1" Text="Wert: " />
<Label Style="{StaticResource DataLabel}" Grid.Column="1" Grid.Row="1" Text="{Binding Value}" />
<Label Style="{StaticResource TitleLabel}" Grid.Column="0" Grid.Row="2" Text="Sensor: " />
<Label Style="{StaticResource DataLabel}" Grid.Column="1" Grid.Row="2" Text="{Binding Sensor.Name}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EvaluationPage : ContentPage
{
private ObservableCollection<SensorValue> SensorValues = new ObservableCollection<SensorValue>();
public EvaluationPage ()
{
InitializeComponent ();
using (var context = new BlepContext(true))
{
var repo = new BLEPRepository(context);
SensorValues = new ObservableCollection<SensorValue>(repo.GetAllSensorValues());
}
}
}
When I run this, my ListView doesn't contain any items. I do not get errors and my app compiles fine. Am I doing something wrong here?
<ListView HasUnevenRows="True" IsVisible="True" x:Name="TableLayout" ItemsSource="{Binding SensorValues}">
you can only bind to public properties, and you need to set a BindingContext for the page
// needs to be a PUBLIC PROPERTY
public ObservableCollection<SensorValue> SensorValues { get; set; }
public EvaluationPage ()
{
InitializeComponent ();
// set the BindingContext
this.BindingContext = this;
using (var context = new BlepContext(true))
{
var repo = new BLEPRepository(context);
SensorValues = new ObservableCollection<SensorValue>(repo.GetAllSensorValues());
}
}

Carousel view does not return anything

I'm implementing a carrousel in my project, but the way I'm implementing it is not returning me anything, to some error in my code? Am I forgetting any options? Reference Xamarin.Forms.CarouselView is already attached
OBS: I am developing crossplataform
<?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="Hanselman.Portable.Views.PodcastPage" Title="{Binding Title}"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
Icon="{Binding Icon}" IsBusy="{Binding IsBusy}"
xmlns:cv="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView">
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout BackgroundColor="White" VerticalOptions="FillAndExpand">
<cv:CarouselView x:Name="car" HeightRequest="200">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical">
<Image Aspect="AspectFit" Source="{Binding imgs}"/>
</StackLayout>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
</AbsoluteLayout>
</ContentPage>
public class Dados
{
public string imgs { get; set; }
}
public PodcastPage()
{
InitializeComponent();
List<Dados> lista = new List<Dados>();
lista.Add(new Dados
{
imgs = "car1.png",
});
lista.Add(new Dados
{
imgs = "car2.png",
});
lista.Add(new Dados
{
imgs = "car3.png",
});
car.ItemsSource = lista;
}
<cv:CarouselView x:Name="MainCarouselView" HeightRequest="100">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="jose" FontSize="50" TextColor="Black"/>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
I tried without image only with the label inside and showing me my name, even so it does not return anything to me, but when I remove the carousel it works, seeing that I verified that my error is in my carousel, it is not an image question

Resources