I have a database that I have created using SQLite. I'm using Xamarin.Forms. I would like to display a carousel of images using CarouselView.FormsPlugin and although I have looked at documentation I have had no luck in displaying it on my app.
I have the CarouselViewRenderer.Init() in the Android MainActivity.cs file. However, no images are displayed.
XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:forms="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
x:Class="HostelRentalApp.HostelDetailsPage">
<ContentPage.Content>
<StackLayout>
<forms:CarouselViewControl x:Name="CRSLImages" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<forms:CarouselViewControl.ItemTemplate HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<DataTemplate>
<Image Source="{Binding .}"/>
</DataTemplate>
</forms:CarouselViewControl.ItemTemplate>
</forms:CarouselViewControl>
</StackLayout>
</ContentPage.Content>
</ContentPage>
CS:
public HostelDetailsPage (HostelInfo hostel)
{
var images = App.Database.GetHostelImageList(0);
this.CRSLImages.ItemsSource = images;
}
SQLite Query:
public List<HostelImages> GetHostelImageList(int id)
{
return database.Query<HostelImages>("SELECT Image FROM HostelImages WHERE Hostel_id = ?", id);
}
The Query is returning the correct rows. As shown, when using a tracepoint, the image filenames are retrieved. However, the images are not shown on the UI. What am I doing wrong? Thank you.
ItemsSource is a List<HostelImages> so your binding path should be
<Image Source="{Binding Image}"/>
Related
I am getting this runtime error saying that the CellView needs a View. I have not found anything on this so far, here on StackOverflow or on google, so I am in the total dark about what needs to be fixed.
I need to set up a list view with 2 sections. the first one is for the bikes that are in the database and the other section is for the ones that we detected but are not saved in the DB yet.
Both sections use the same UI (cell) and so I need to be able to have a sliding button (ContextAction MenuItem) in the first section and for the second section this action needs to be disabled/removed.
If it's not possible then I would need to have the action for the second section "Add" instead of "Forget".
This is why I created a subclass.
this is my code.
(edit: corections)
---- .xaml file ----
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EGrid18.Components.BikeSelectionCell"
x:Name="ThisCell">
<ViewCell.View>
<StackLayout>
<Grid ColumnSpacing="10"
BindingContext="{x:Reference ThisCell}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding BikeName}"
StyleClass="bikecellname"
Grid.Row="0"
Grid.Column="0"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand"/>
<Image Source="{Binding Image}"
HeightRequest="16"
WidthRequest="16"
VerticalOptions="Center"
Aspect="AspectFit"
Grid.Column="1"
Grid.Row="0"/>
<Label Text="{Binding Distence, StringFormat='{0:F2} M'}"
Grid.Row="0"
Grid.Column="2"
VerticalOptions="Center"/>
</Grid>
</StackLayout>
</ViewCell.View>
</ViewCell>
---- .cs file ----
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EGrid18.Components
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BikeSelectionCell : ViewCell
{
public static BindableProperty BikeNameProperty =
BindableProperty.Create(nameof(BikeName), typeof(string), typeof(BikeSelectionCell), string.Empty);
public string BikeName
{
get => (string)GetValue(BikeNameProperty);
set => SetValue(BikeNameProperty, value);
}
public static BindableProperty ImageProperty =
BindableProperty.Create(nameof(Image), typeof(string), typeof(BikeSelectionCell), string.Empty);
public string Image
{
get => (string)GetValue(ImageProperty);
set => SetValue(ImageProperty, value);
}
public static BindableProperty DistenceProperty =
BindableProperty.Create(nameof(Distence), typeof(double), typeof(BikeSelectionCell), 0.0);
public double Distence
{
get => (double)GetValue(DistenceProperty);
set => SetValue(DistenceProperty, value);
}
public static readonly BindableProperty ForgetCommandProperty =
BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(BikeSelectionCell), null);
public ICommand ForgetCommand
{
get { return (ICommand)GetValue(ForgetCommandProperty); }
set { SetValue(ForgetCommandProperty, value); }
}
public Command OnForget => new Command(() => Execute(ForgetCommand));
// Helper method for invoking commands safely
public static void Execute(ICommand command)
{
if (command == null) return;
if (command.CanExecute(null))
{
command.Execute(null);
}
}
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if(propertyName == nameof(Image))
{
this.ContextActions.Clear();
if (Image != "unknown")
{
this.ContextActions.Add(new MenuItem()
{
Text = "Forget",
Command = ForgetCommand,
CommandParameter = this
});
}
}
}
}
}
--- the .xaml file that consumes the CellView subclass ---
<?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:vm="clr-namespace:EGrid18.ViewModels"
xmlns:iOS="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:components="clr-namespace:EGrid18.Components"
iOS:Page.UseSafeArea="True"
x:Class="EGrid18.Views.BikeSelectionPage"
Title="Bike Selection List">
<ContentPage.Resources>
<ResourceDictionary>
<vm:BikeListViewModel x:Key="vm"/>
<StyleSheet Source="/CSS/Styles.css"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="ScanButton" Text="Scan"
Command="{Binding Source={StaticResource vm}, Path=OnScanCommand}"
CommandParameter="{Binding Source={StaticResource vm}, Path=IsScanning}" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Margin="8,8,8,8">
<Label Text="Bike Selection Page"
StyleClass="titlelabel"/>
<ListView x:Name="ListView"
BindingContext="{StaticResource vm}"
StyleClass="listview"
ItemsSource="{Binding BikeList}"
IsGroupingEnabled="True"
SelectedItem="{Binding SelectedBike}"
Margin="8,8,8,8">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Heading}"
VerticalOptions="Center"
Margin="8,8,8,8"/>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<components:BikeSelectionCell
BikeName="{Binding Name}"
Image="{Binding Image}"
Distence="{Binding Distence}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
A ViewCell is not a View - it isn't part of View heirarchy. It is a "wrapper" that is needed by ListView, around each item.
Personally, I never create subclasses of ViewCell, though that can be done.
IMHO, Its more straightforward to make a custom View, then wrap that in <ViewCell> to use with ListView.
As a View, you can inherit from any view class. If you don't know what else to use, inherit from ContentView. (Or from StackLayout, if need to add multiple children views.) In your case, your View is a StackLayout.
public partial class BikeSelectionView : StackLayout
... // All the lines of code you have in BikeSelectionCell go here.
xaml:
<StackLayout ... x:Name="ThisCell">
<Grid ColumnSpacing="10" ...>
... All the remaining lines of code from your xaml ...
</StackLayout>
Usage inside ListView's ItemTemplate:
<DataTemplate>
<ViewCell>
<components:BikeSelectionView
BikeName="{Binding Name}"
Image="{Binding Image}"
Distence="{Binding Distence}"/>
</ViewCell>
</DataTemplate>
One advantage of this approach is if you switch from ListView to CollectionView (which does not use ViewCells), you can still use the custom class:
<CollectionView.ItemTemplate>
<DataTemplate>
<components:BikeSelectionView ... />
</DataTemplate>
</CollectionView.ItemTemplate>
The error was coming from a missing constructor that needed to initialize the Component.
public BikeSelectionCell()
{
InitializeComponent();
}
In the end I used the suggestion ToolmakerSteve. I also used a custom DataTemplateSelector to set specifics DataTemplate for the 2 different sections
I am setting this as the answer for any one looking for this problem as the problem was really the missing call to InitializeComponent();
I am using TabView in my project. I've installed Xamarin.community.toolkit.
I am trying to add Content for TabViewitem programmatically instead of xaml because each ContentView of TabViewItem has service calls in it's constructor which is causing the issue when all the TabViewItems load at once.
Below is my code:
<xcl:TabView x:Name="MainTabView"
TabStripPlacement="Top">
<xcl:TabViewItem
x:Name="Tab1"
Text="Details"
Margin="16,0,16,0"
TextColor="Black"
FontFamily="{StaticResource SFProRegular}"
TextColorSelected="Black"
FontSize="15">
</xcl:TabViewItem>
------
</xcl:TabView>
And I 'm trying to add Content to TabViewItem programatically like below (Page1 is a ContentView)
var stackPanel = new StackLayout { Orientation = StackOrientation.Vertical };
stackPanel.Children.Add(new Page1());
DetailsTabView.Content = stackPanel;
But the UI is not rendering in my app.
The same works If I add the Page1 like below:
<xcl:TabView x:Name="MainTabView"
TabStripPlacement="Top" >
<xcl:TabViewItem
x:Name="Tab1"
Text="Details"
Margin="16,0,16,0"
TextColor="Black"
FontFamily="{StaticResource SFProRegular}"
TextColorSelected="Black"
FontSize="15">
<template:Page1 />
</xcl:TabViewItem>
------
</xcl:TabView>
Any help is appreciated!
And I 'm trying to add Content to TabViewItem programatically like below (Page1 is a ContentView)
If you want to add one COntentview in one TabViewItem by code behind, you can take a look:
<xct:TabView
x:Name="mytabview"
TabIndicatorColor="Yellow"
TabStripBackgroundColor="Blue"
TabStripHeight="60"
TabStripPlacement="Bottom">
<xct:TabViewItem
x:Name="tb1"
FontSize="12"
Text="Tab 1"
TextColor="White"
TextColorSelected="Yellow">
<StackLayout />
</xct:TabViewItem>
<xct:TabViewItem
x:Name="tb2"
FontSize="12"
Text="Tab 2"
TextColor="White"
TextColorSelected="Yellow">
</xct:TabViewItem>
</xct:TabView>
Then adding ContentView to TabViewItem.
public MainPage()
{
InitializeComponent();
mytabview.TabItems[0].Content = new contentview1();
mytabview.TabItems[1].Content = new contentview2();
}
Note: please forget to add Stacklayout or other layout inside TabViewItem by xaml, then code you add contentview will be effective.
you need to do somethig like this
<xct:TabView TabItemsSource="{Binding TabVms}"
TabStripPlacement="Top"
TabStripBackgroundColor="LightGray"
TabIndicatorColor="Gray" IsTabStripVisible="True">
<xct:TabView.TabViewItemDataTemplate>
<DataTemplate>
<Grid>
// tabs
</Grid>
</DataTemplate>
</xct:TabView.TabViewItemDataTemplate>
<xct:TabView.TabContentDataTemplate>
<DataTemplate>
<Grid>
// content`enter code here`
</Grid>
</DataTemplate>
</xct:TabView.TabContentDataTemplate>
</xct:TabView>
We want to implement drag and drop functionality in Xamarin forms
and in this user should be able to drag an emoji from 1 place, and put on another. We don’t want the source emoji to go away though and should be able to come to know on which employee, rating is given .
Image how it is before
Image how it is after
Question also posted on:
https://forums.xamarin.com/discussion/184104/drag-and-drop-on-xamarin-forms/p1?new=1
We have checked a few links like below, but none of them seem to work:
Xamarin Forms Drag Image between Views
https://blog.francois.raminosona.com/drag-and-drop-in-xamarin-forms/
Will appreciate if could get some tips on how to do it and even if this was possible on forms?
You could check the code below.
xaml:
<StackLayout Margin="10">
<StackLayout Margin="10" Orientation="Horizontal">
<components:DragAndDropSample3ReceivingView
BackgroundColor="Beige"
HeightRequest="80"
WidthRequest="80" />
<components:DragAndDropSample3ReceivingView
BackgroundColor="Beige"
HeightRequest="80"
WidthRequest="80" />
<components:DragAndDropSample3ReceivingView
BackgroundColor="Beige"
HeightRequest="80"
WidthRequest="80" />
</StackLayout>
<BoxView
BackgroundColor="Blue"
HeightRequest="5"
WidthRequest="3" />
<StackLayout Margin="10" Orientation="Horizontal">
<components:DragAndDropSample3MovingView
BackgroundColor="Red"
CornerRadius="40"
HeightRequest="40"
WidthRequest="40" />
<components:DragAndDropSample3MovingView
BackgroundColor="Green"
CornerRadius="40"
HeightRequest="40"
WidthRequest="40" />
</StackLayout>
</StackLayout>
Code Behind:
public void OnDropReceived(IDragAndDropMovingView view)
{
if (view is DragAndDropSample3MovingView sender)
{
var control = new DragAndDropSample3MovingView()
{
BackgroundColor=sender.BackgroundColor,
CornerRadius=sender.CornerRadius,
WidthRequest=sender.WidthRequest,
HeightRequest=sender.HeightRequest,
};
Content = control;
}
}
Screenshot:
You could check the source file from the code project for reference.
https://github.com/WendyZang/Test/tree/master/Drag_Drop_Controls/Xamarin-Developer-Sample-master
The documentation says that I should use the page carousel for the place, this is a carousel view. But I do not understand how to do this.
I have three completely different pages. If earlier I could do like this. look how easy it is.
<CarouselPage 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"
x:Class="test.Corusel">
<CarouselPage.Children>
<local:Page1></local:Page1>
<local:Page2></local:Page2>
</CarouselPage.Children>
Now, when I try to make a look identical to the CarouselPage, I just have a white screen.
<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"
x:Class="test.Corusel">
<CarouselView>
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<local:View1></local:View1>
<local:View2></local:View2>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentPage>
People tell me that there should be an itemSource. Without itemSource, content will not be displayed. But as I understand it, itemSource does not allow you to make different layouts for data.
I don’t understand how I can make a copy of СarouselPage from СarouselView (or CollectionView) if:
My pages have different layouts!
To load content into different layouts, I use different functions!
In my knowledge what you are looking for is the DataTemplateSelector
Create a subclass of Selector with properties that hold the templates:
public class PersonDataTemplateSelector : DataTemplateSelector
{
public DataTemplate ValidTemplate { get; set; }
public DataTemplate InvalidTemplate { get; set; }
protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
{
return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
}
}
Add them to your resources:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="validPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="invalidPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
ValidTemplate="{StaticResource validPersonTemplate}"
InvalidTemplate="{StaticResource invalidPersonTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
Use them:
ItemTemplate="{StaticResource personDataTemplateSelector}"
For more information check the microsoft documents: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector
Can I create a view including Entry Progress bar or others to make a view which I can use in other places?
for example I want to create a card view which I can use to list the lists.
I can only write in the list not to write the card in every list.
Yes, you can create a custom view and use it in the MainPage or other Pages, Views you want.
To create a custom view, add a new item --> ContentView,let's call it CardView:
In .cs of CardView:
public partial class CardView : ContentView
{
public CardView()
{
InitializeComponent();
}
}
In xaml of CardView, add your labels,progressbar, entry there:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView 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="App35.CardView">
<ContentView.Content>
<StackLayout>
<Label Text="Hello Xamarin.Forms!" />
<ProgressBar Progress="0.5" />
<Entry Placeholder="I'm entry"/>
</StackLayout>
</ContentView.Content>
</ContentView>
To use it in MainPage, in listView or in the page:
<StackLayout>
<projectName:CardView HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
<ListView x:Name="listView" RowHeight="70">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>mono</x:String>
<x:String>monodroid</x:String>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<projectName:CardView HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
I upload a sample here and you can check.
Yes you can do that using ContentView, if you want to use it as views
Or you can make ViewCells if you want to use it in ListViews. Its easy and almost every project does that.
You can refer this link :- https://xamarinhelp.com/xamarin-forms-user-control/
Let me know if you have more questions on this. Thanks!