Avoid keyboard hiding while navigating focus between different Entry - xamarin

I navigate focus from an Entry to another Entry inside a AbsoluteLayout through a button click.
On every focus navigation the keyboard hide and again comes back to visiblity. I want the Keyboard to avoid hiding if the Next child to be focused is an Entry.
Xaml code
<Grid>
<ScrollView>
<local:CustomLayout
x:Name="entryStack"
BindableLayout.ItemsSource="{Binding SomeItems}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Entry
WidthRequest="100"
Focused="Entry_Focused"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</local:CustomLayout>
</ScrollView>
<Button VerticalOptions="Start" HorizontalOptions="End" Text="NextField" Clicked="Button_Clicked"/>
</Grid>
CustomLayout inheriting AbsoluteLayout
public class CustomLayout : AbsoluteLayout
{
public CustomLayout()
{
}
protected override void OnChildAdded(Element child)
{
base.OnChildAdded(child);
var childElement = (child as View);
var index = this.Children.IndexOf(childElement);
childElement.TranslationY = index * 30;
}
}
Xaml.cs
public partial class MainPage : ContentPage
{
public List<string> SomeItems { get; set; }
int i = 0;
public MainPage()
{
InitializeComponent();
this.SomeItems = new List<string>()
{
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
"One",
};
this.BindingContext = this;
}
void Button_Clicked(System.Object sender, System.EventArgs e)
{
i = i+1;
(entryStack.Children[i] as Entry).Focus();
}
void Entry_Focused(System.Object sender, Xamarin.Forms.FocusEventArgs e)
{
i = entryStack.Children.IndexOf((sender as Entry));
}
}
Is this possible to achieve. Am I doing something wrong here??

Related

Bindable Layouts > Binding: Property X not found on ViewModel

I have simple XAML page with code like this:
<StackLayout BindableLayout.ItemsSource="{Binding Data}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label BackgroundColor="{Binding Color}"
Text="{Binding Text}"
FontAttributes="Italic"
FontSize="20"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
HeightRequest="105"
Margin="25" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
In the view page code behind I have:
public partial class DataView
{
public DataView()
{
InitializeComponent();
BindingContext = new ViewModel();
}
...
}
Data is:
public class ViewModel
{
public ViewModel()
{
Data = new ObservableCollection()<Model> {
new Model { Text = "Pink", Color = Color.DeepPink },
new Model { Text = "Crimson", Color = Color.Crimson },
new Model { Text = "Aqua", Color = Color.Aqua },
new Model { Text = "Blue", Color = Color.DeepSkyBlue },
new Model { Text = "BurlyWood", Color = Color.BurlyWood }, };
}
public ObservableCollection<Model> Data { get; set; }
}
public class Model
{
public Color Color { get; set; }
public string Text { get; set; }
}
However, on compile, I get:
Binding: Property "Color" not found on "MyComp.ViewModel".
Seems like its searching for Color in ViewModel instead of parent (Data).
I'm using the latest Xamarin.Forms 4.8.0, .NET Standard 2.0 and Visual Studio 2019 16.7.4.
I tested the xaml code, it still works fine.Check the gif: https://us.v-cdn.net/5019960/uploads/editor/pd/aa0fp5pwnvkl.gif
Here is the related code, you could refer to it.
Page.xaml
<StackLayout x:Name="expanderLayout" BindableLayout.ItemsSource="{Binding Data}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Expander>
<Expander.Header>
<Grid>
<Label BackgroundColor="{Binding Color}"/>
</Grid>
</Expander.Header>
<Expander.ContentTemplate>
<DataTemplate>
<Label
Text="{Binding Text}"
FontAttributes="Italic"
FontSize="20"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
HeightRequest="105"
Margin="25" />
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Page.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new ViewModel();
}
}
Model class and ViewModel class
public class ViewModel
{
public ViewModel()
{
Data = new System.Collections.ObjectModel.ObservableCollection<Model>() {
new Model { Text = "Pink", Color = Color.DeepPink },
new Model { Text = "Crimson", Color = Color.Crimson },
new Model { Text = "Aqua", Color = Color.Aqua },
new Model { Text = "Blue", Color = Color.DeepSkyBlue },
new Model { Text = "BurlyWood", Color = Color.BurlyWood }, };
}
public ObservableCollection<Model> Data { get; set; }
}
public class Model
{
public Color Color { get; set; }
public string Text { get; set; }
}
I tried run your code and see nothing wrong with it
Apart from some slight typo in your question, I have it as this
public ViewModel()
{
Data = new ObservableCollection<Model>
{
new Model {Text = "Pink", Color = Color.DeepPink},
new Model {Text = "Crimson", Color = Color.Crimson},
new Model {Text = "Aqua", Color = Color.Aqua},
new Model {Text = "Blue", Color = Color.DeepSkyBlue},
new Model {Text = "BurlyWood", Color = Color.BurlyWood},
};
}
, maybe try clean/rebuild solution and run again?

How do i add items to a observablecollection from another list view

Hi I am a beginner with Xamarin forms and need some help. I have tried looking for this method everywhere.
I have a List view with a lot of animal names. When a item is clicked it shows more info about that particular animal. I have added a button that is on each animals info page. I would like to click that "add" button, that would then add the name off the animal to another List view.
But I am stuck on how to do this, any help would be greatly appreciated.
this is the first list page in code behind
public partial class BirdListAZ : ContentPage
{
IEnumerable<birdlistmodel> GetBirds(string searchText = null)
{
var birds = new List<birdlistmodel>
{
new birdlistmodel (){Id = 1, BirdNames = "Apalis, Bar-throated" },
new birdlistmodel (){Id = 2, BirdNames = "Apalis, Yellow-breasted"},//there are alot more birds here
};
if (String.IsNullOrWhiteSpace(searchText))
return birds;
var lowerBirds = searchText.ToLower();
return birds.Where(c => c.BirdNames.ToLower().StartsWith(lowerBirds));
}
public BirdListAZ()
{
InitializeComponent();
blistview.ItemsSource = GetBirds();
}
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
blistview.ItemsSource = GetBirds(e.NewTextValue);
}
private void blistview_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var birds = e.SelectedItem as birdlistmodel;
Navigation.PushAsync(new BirdPages(birds.BirdNames, birds.BirdSelect));
}
}
}
this is the content page for that code behind
<ScrollView HeightRequest="3000">
<StackLayout>
<SearchBar
TextChanged="SearchBar_TextChanged"
Placeholder="Search Bird"
PlaceholderColor="Gray"
HorizontalTextAlignment="Center"
FontSize="Small"
FontAttributes="Italic"
VerticalOptions="Center" HorizontalOptions="Start"/>
<ListView x:Name="blistview" BackgroundColor ="AliceBlue" HasUnevenRows="True" ItemSelected="blistview_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="5">
<Label Text="{Binding BirdNames}" HorizontalOptions="StartAndExpand" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ScrollView>
when item is clicked on list it displays that info in a separate page
the contentpage
<ContentPage.Content>
<StackLayout>
<Label x:Name="BirdNameCall" FontSize="30" FontAttributes="Bold"
VerticalOptions="StartAndExpand"
HorizontalOptions="CenterAndExpand" />
<Button Text="+" x:Name="AddToList" VerticalOptions="Center" HorizontalOptions="Center" WidthRequest="200" HeightRequest="100"
FontSize="30" BackgroundColor="Transparent" Clicked="AddToList_Clicked"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
So this is what i have done. I know the filewritealltext makes a new file each time. how can i just add to that file so a new file is not created?
public BirdPages(string BirdNames, Button BirdSelect)
{
InitializeComponent();
BirdNameCall.Text = BirdNames;
AddToList = BirdSelect;
localPath = Path.Combine(FileSystem.AppDataDirectory, birdfile);
}
const string birdfile = "birdlist.txt";
string localPath;
private void AddToList_Clicked(object sender, EventArgs e)
{
string BirdNames = BirdNameCall.Text;
File.WriteAllText(localPath, BirdNames);
DisplayAlert(BirdNames, "added to list", "Ok");
}
So it works when i populate the list view but it will be a letter per row and not the entire string in a row
public partial class myBirdList : ContentPage
{
public myBirdList()
{
InitializeComponent();
localPath = Path.Combine(FileSystem.AppDataDirectory, birdfile);
birdlistview.ItemsSource = File.ReadAllText(localPath);
}
const string birdfile = "birdlist.txt";
string localPath;
}
So this is what I have done. I had to change a bit.
The added Bird Name needs to go to a blank list. So I created a new Observable Collection here. And this is where the Bird Name needs to be added.
public partial class myBirdList : ContentPage
{
public ObservableCollection<string> Birdsadded { get; set; } = new ObservableCollection<string>();
public myBirdList()
{
InitializeComponent();
BindingContext = this;
MessagingCenter.Subscribe<BirdPages, birdlistmodel>(this, "Add", (sender, arg) =>
{
Birdsadded.Add(arg.ToString());
});
}
}
}
Then the sender is where I am having issues. And can't figure out how to send the bird name.
public partial class BirdPages : ContentPage
{
public BirdPages(string BirdNames, Button BirdSelect)
{
InitializeComponent();
BirdNameCall.Text = BirdNames;
AddToList = BirdSelect;
}
private void AddToList_Clicked(object sender, EventArgs e)
{
birdlistmodel bird = xxx// this is what i don't understand, what should be added here
MessagingCenter.Send<BirdListAZ, birdlistmodel>(this, "Add", bird );
}
}
}
thanks for your time and input I appreciate it.
You could use MessagingCenter to achieve this.
Using MessagingCenter.Send to pass the new data in your AddToList_Clicked method of BirdPages
then you will get the callback in another page which you want to add the new items with MessagingCenter.Subscribe method.In the callback method,you could add the new data to the new listview.
For example:
In the listview page which you want display a list and add the new data.
public partial class BirdListAZ : ContentPage
{
public ObservableCollection<string> Birdsadded { get; set; } = new ObservableCollection<string>();
public BirdListAZ()
{
InitializeComponent();
blistview.ItemsSource = GetBirds();
MessagingCenter.Subscribe<BirdListAZ, string>(this, "Add", async (sender, arg) =>
{
Birdsadded.Add(arg);// when you click add button in other page,it will handle this
});
}
}
in the page which you want to add the data:
public partial class BirdPages : ContentPage
{
public BirdPages(string BirdNames, Button BirdSelect)
{
InitializeComponent();
BirdNameCall.Text = BirdNames;
AddToList = BirdSelect;
}
private void AddToList_Clicked(object sender, EventArgs e)
{
string birdname = xxxx;
MessagingCenter.Send<BirdListAZ, string>(this, "Add",birdname );
}
}
OK so i got it to work to some extent. I am not creating and writing to a txt file and then reading from it in mybirdlist page. This is where i write to text file
public BirdPages(string BirdNames, Button BirdSelect)
{
InitializeComponent();
BirdNameCall.Text = BirdNames;
AddToList = BirdSelect;
localPath = Path.Combine(FileSystem.AppDataDirectory, birdfile);
}
const string birdfile = "birdlist.txt";
string localPath;
private void AddToList_Clicked(object sender, EventArgs e)
{
string BirdNames = BirdNameCall.Text;
using (var writer = new StreamWriter(localPath, true))
{
writer.WriteLine(BirdNames);
}
DisplayAlert(BirdNames, "added to list", "Ok");
}
Then i read from it into a list. Last question i have is how can i read each name into a lable. Now all the added birds displays in one label. And is it possible to not duplicate a name? Here is the code
public myBirdList()
{
localPath = Path.Combine(FileSystem.AppDataDirectory, birdfile);
string text = "";
using (var reader = new System.IO.StreamReader(localPath))
{
text = reader.ReadToEnd();
}
InitializeComponent();
birdlistview.ItemsSource = new List<birdlistmodel>
{
new birdlistmodel {Voellist = text }
};
}
const string birdfile = "birdlist.txt";
string localPath;
}

Xamarin Forms: How to Change the textcolor of Collectionview SelectedItem?

I have a CarouselPage having 5 children and every child has a horizontal collection view. When selecting an item in Collectionview or swiping the pages, I need to give a different text color and need to add an underline for the selected item. I have tried like below:
CarouselHomePage.cs
public partial class CarouselHomePage : CarouselPage
{
public List<Activity> activityList { get; set; }
public CarouselHomePage()
{
InitializeComponent();
activityList = new List<Activity>();
AddActivities();
MessagingCenter.Subscribe<App, string>((App)Xamarin.Forms.Application.Current, "child", (s, child) =>
{
CurrentPage = Children[Int32.Parse(child)];
});
}
private void AddActivities()
{
activityList.Add(new Activity() { Title = "PageNumber1" });
activityList.Add(new Activity() { Title = "PageNumber2" });
activityList.Add(new Activity() { Title = "PageNumber3" });
activityList.Add(new Activity() { Title = "PageNumber4" });
activityList.Add(new Activity() { Title = "PageNumber5" });
AddChild(activityList);
}
public void AddChild(List<Activity> activityList)
{
this.Children.Add(new PageNumber1(activityList));
this.Children.Add(new PageNumber2(activityList));
this.Children.Add(new PageNumber3(activityList));
this.Children.Add(new PageNumber4(activityList));
this.Children.Add(new PageNumber5(activityList));
}
}
Activity.cs
public class Activity
{
public string Title { get; set; }
public bool visibility { get; set; }
public bool Visibility
{
set
{
if (value != null)
{
visibility = value;
NotifyPropertyChanged();
}
}
get
{
return visibility;
}
}
private Color textColor;
public Color TextColor
{
set
{
if (value != null)
{
textColor = value;
NotifyPropertyChanged();
}
}
get
{
return textColor;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
PageNumber1.xaml
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<CollectionView
SelectionMode="Single"
x:Name="ActivityList"
Margin="5,10,5,10"
SelectionChanged="TagItemTapped"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Orientation="Vertical"
Margin="15">
<Label
TextColor="{Binding TextColor}"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="{Binding Title}">
<Label.FontSize>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>18</OnIdiom.Phone>
<OnIdiom.Tablet>27</OnIdiom.Tablet>
<OnIdiom.Desktop>18</OnIdiom.Desktop>
</OnIdiom>
</Label.FontSize>
</Label>
<BoxView
HeightRequest="2"
IsVisible="{Binding Visibility}"
BackgroundColor="{Binding TextColor}"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Start"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>30</OnIdiom.Phone>
<OnIdiom.Tablet>60</OnIdiom.Tablet>
<OnIdiom.Desktop>30</OnIdiom.Desktop>
</OnIdiom>
</CollectionView.HeightRequest>
</CollectionView>
<Label Text="Welcome to PageNumber1"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
PageNumber1.xaml.cs
public partial class PageNumber1 : ContentPage
{
public PageNumber1(List<Activity> activityList)
{
InitializeComponent();
if (activityList == null)
{
ActivityList.IsVisible = false;
}
else
{
for (int i = 0; i < activityList.Count; i++)
{
if (activityList[i].Title == "PageNumber1")
{
activityList[i].TextColor = Color.FromHex("#26b4d8");
activityList[i].Visibility = true;
}
else
{
activityList[i].TextColor = Color.Gray;
activityList[i].Visibility = false;
}
}
ActivityList.ItemsSource = activityList;
}
}
public void TagItemTapped(object sender, SelectionChangedEventArgs e)
{
var selectedItem = (e.CurrentSelection.FirstOrDefault() as Activity);
if (selectedItem != null)
{
string childnumber = "";
if (selectedItem.Title == "PageNumber1")
{
childnumber = "0";
}
else if (selectedItem.Title == "PageNumber2")
{
childnumber = "1";
}
else if (selectedItem.Title == "PageNumber3")
{
childnumber = "2";
}
else if (selectedItem.Title == "PageNumber4")
{
childnumber = "3";
}
else if (selectedItem.Title == "PageNumber5")
{
childnumber = "4";
}
MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "child", childnumber);
}
}
}
I have added the same code on all the other child pages with the corresponding title in the if statement. But the selected page title color is not working and underline is not showing.
Screenshot:
Also if I select the last item in the collectionview, I need to scroll the collection on the last child to the last item. For this I have used ScrollTo feature of Collectioview. But that is also not working.
protected override void OnAppearing()
{
ActivityList.ScrollTo(4);
}
The above code will work if I manually swipe the pages. When directly tap the collectionview item, the scrolling is not working.
I have uploaded a sample project here.
About underline not showing , the reason is HeightRequest of CollectionView setted too small with 30 .
Modify that to above 35 , it will show correcttly . Such as :
<CollectionView.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>40</OnIdiom.Phone>
<OnIdiom.Tablet>60</OnIdiom.Tablet>
<OnIdiom.Desktop>30</OnIdiom.Desktop>
</OnIdiom>
</CollectionView.HeightRequest>
The effect :
About selected problem , this is the sample project here .

Two search bar Xamarin Forms

I have a question here (I imagine it is for beginners: P).
I have a listview and a searchbar already working. I can make the right filter.
Then my question comes in, this listview has more than one column.
I can't think of a way to make 2 complementary filters.
For example:
Filter column 1 and then filter the result of that initial filter by column 2 (with another searchbar), that is, a filter on top of another filter.
My ListViewItem is like this with the filter:
C#
void InitList()
{
Items = new List<ListViewItem>
{
new ListViewItem { Name = "Guilherme", Bairro = "BOTAFOGO"},
new ListViewItem { Name = "João", Bairro = "FLAMENGO"},
new ListViewItem { Name = "Maria", Bairro = "CENTRO"}
}
}
void InitSearchBarBloco()
{
sb_search_bloco.TextChanged += (s, e) => FilterItem(sb_search_bloco.Text);
sb_search_bloco.SearchButtonPressed += (s, e) =>
FilterItem(sb_search_bloco.Text);
}
private void FilterItem(string filter)
{
exampleListView.BeginRefresh();
if (string.IsNullOrWhiteSpace(filter))
{
exampleListView.ItemsSource = Items;
}
else
{
exampleListView.ItemsSource = Items.Where(x => x.Name.ToLower().Contains(filter.ToLower()));
}
exampleListView.EndRefresh();
}
XAML
<SearchBar x:Name="sb_search_bloco" Placeholder="Nome..." />
<ListView x:Name="exampleListView" RowHeight="22" SelectedItem="{Binding Name}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<Grid>
<Label Text="{Binding Name}" LineBreakMode="TailTruncation" />
<Label Grid.Column="1" Text="{Binding Bairro}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
With this structure I can implement this ... "filtrate filter"?
thanks
I guess the below code should do fine for you. You just need to alter your linq code inside the FilterItem(string filter) method to achieve your requirement.
Note:
I have used OR condition inside the where clause to search if the enter text is available in both Name and Bairro. However, you can modify the condition as you require.
private void FilterItem(string filter)
{
exampleListView.BeginRefresh();
if (string.IsNullOrWhiteSpace(filter))
{
exampleListView.ItemsSource = Items;
}
else
{
//Alter the condition like below or based on requirement to achieve the desired result.
exampleListView.ItemsSource = Items.Where(x => x.Name.ToLower().Contains(filter.ToLower()) || x.Bairro.ToLower().Contains(filter.ToLower()));
}
exampleListView.EndRefresh();
}
I make a sample code for your referece.
xmal:
<StackLayout>
<StackLayout>
<SearchBar x:Name="sb_search_bloco" Placeholder="Nome..." TextChanged="sb_search_bloco_TextChanged"/>
<SearchBar x:Name="searchBar2" Margin="0,10" TextChanged="searchBar2_TextChanged" />
</StackLayout>
<ListView
x:Name="exampleListView"
RowHeight="22"
ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label LineBreakMode="TailTruncation" Text="{Binding Name}" />
<Label Grid.Column="1" Text="{Binding Bairro}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
ListViewItem.cs
public class ListViewItem
{
public string Name { get; set; }
public string Bairro { get; set; }
}
MainPage.xml.cs
public partial class MainPage : ContentPage
{
public List<ListViewItem> Items { get; set; }
public MainPage()
{
InitializeComponent();
Items = new List<ListViewItem>
{
new ListViewItem { Name = "AAAA", Bairro = "BBCFS"},
new ListViewItem { Name = "ABBB", Bairro = "SSDCA"},
new ListViewItem { Name = "AAAA", Bairro = "AAAD"},
new ListViewItem { Name = "CCCC", Bairro = "SSS"},
new ListViewItem { Name = "DAAB", Bairro = "CCC"},
new ListViewItem { Name = "DDDC", Bairro = "QWDAS"}
};
this.BindingContext = this;
}
private void sb_search_bloco_TextChanged(object sender, TextChangedEventArgs e)
{
exampleListView.ItemsSource = FilterItem1(e.NewTextValue);
}
IEnumerable<ListViewItem> FilterItem1(string filter = null)
{
if (string.IsNullOrEmpty(filter))
return Items;
return Items.Where(p => p.Name.StartsWith(filter));
}
private void searchBar2_TextChanged(object sender, TextChangedEventArgs e)
{
exampleListView.ItemsSource = FilterItem2(e.NewTextValue);
}
IEnumerable<ListViewItem> FilterItem2(string filter = null)
{
if (string.IsNullOrEmpty(filter))
return Items;
return Items.Where(p => p.Bairro.StartsWith(filter));
}
}

Telerik UI for Xamarin: Property not found for RadListView Binding

I am working on an Android app with Xamarin, using Telerik UI.
The following error is raised when trying to bind a property to a Telerik ListViewTextCell in a RadListView:
[0:] Binding: 'Author' property not found on 'Book', target property: 'Telerik.XamarinForms.DataControls.ListView.ListViewTextCell.Detail'
This happens in even the most minimal cases. Below is an example, drawn largely from the ListView documentation itself.
PageTest.cs:
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
using Telerik.XamarinForms.DataControls;
using Telerik.XamarinForms.DataControls.ListView;
namespace MyTelerikApp
{
[DesignTimeVisible(false)]
public partial class PageTest : ContentPage
{
public PageTest()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
var listView = new RadListView
{
ItemsSource = new ViewModel().Source,
ItemTemplate = new DataTemplate(() =>
{
var cell = new ListViewTextCell
{
TextColor = Color.Black,
DetailColor = Color.Gray,
};
cell.SetBinding(ListViewTextCell.TextProperty, new Binding(nameof(Book.Title)));
cell.SetBinding(ListViewTextCell.DetailProperty, new Binding(nameof(Book.Author)));
return cell;
}),
LayoutDefinition = new ListViewLinearLayout { ItemLength = 70 }
};
MainPageContent.Children.Add(listView);
}
}
}
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
public class ViewModel
{
public ViewModel()
{
this.Source = new List<Book>{
new Book{ Title = "The Fault in Our Stars ", Author = "John Green"},
new Book{ Title = "Divergent", Author = "Veronica Roth"},
new Book{ Title = "Gone Girl", Author = "Gillian Flynn"},
new Book{ Title = "Clockwork Angel", Author = "Cassandra Clare"},
new Book{ Title = "The Martian", Author = "Andy Weir"},
new Book{ Title = "Ready Player One", Author = "Ernest Cline"},
new Book{ Title = "The Lost Hero", Author = "Rick Riordan"},
new Book{ Title = "All the Light We Cannot See", Author = "Anthony Doerr"},
new Book{ Title = "Cinder", Author = "Marissa Meyer"},
new Book{ Title = "Me Before You", Author = "Jojo Moyes"},
new Book{ Title = "The Night Circus", Author = "Erin Morgenstern"},
};
}
public List<Book> Source { get; set; }
}
PageText.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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="GeoGIS.views.PageTest">
<StackLayout x:Name="MainPageContent">
</StackLayout>
</ContentPage>
After some searching, it seems that a BindingContext is necessary, but I couldn't get that to work either.
I didn't found BindingContext from your code.And I guess you confused the two usages of ContentPage(XAML and C# ).
When we created a contentpage,we have two choices(XAML and C#) as follows:
1.When we choose the ContentPage(c#),in this case, there is no xaml.And we can do like this:
public class TestPage1 : ContentPage
{
public TestPage1 ()
{
var listView = new RadListView
{
BackgroundColor = Color.White,
ItemsSource = new ViewModel().Source,
ItemTemplate = new DataTemplate(() =>
{
var cell = new ListViewTextCell
{
TextColor = Color.Black,
DetailColor = Color.Gray,
};
cell.SetBinding(ListViewTextCell.TextProperty, new Binding(nameof(Book.Title)));
cell.SetBinding(ListViewTextCell.DetailProperty, new Binding(nameof(Book.Author)));
return cell;
}),
LayoutDefinition = new ListViewLinearLayout { ItemLength = 70 },
};
Content = new StackLayout {
Children = {
listView
}
};
}
}
2.When we choose the ContentPage,in this case, code has xaml.We can do like this.
Put the followinging code in your xaml
<StackLayout>
<telerikDataControls:RadListView ItemsSource="{Binding Source}" BackgroundColor="White" x:Name="listView">
<telerikDataControls:RadListView.BindingContext>
<local:ViewModel />
</telerikDataControls:RadListView.BindingContext>
<telerikDataControls:RadListView.ItemTemplate>
<DataTemplate>
<telerikListView:ListViewTextCell Text="{Binding Title}" Detail="{Binding Author}" TextColor="Black" DetailColor="Gray" />
</DataTemplate>
</telerikDataControls:RadListView.ItemTemplate>
<telerikDataControls:RadListView.LayoutDefinition>
<telerikListView:ListViewLinearLayout ItemLength="70" />
</telerikDataControls:RadListView.LayoutDefinition>
</telerikDataControls:RadListView>
</StackLayout>
And remove the method OnAppearing() from your code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
//BindingContext = new ViewModel();
}
protected override void OnAppearing()
{
base.OnAppearing();
}
}
From above code,we can found the BindingContext,it is necessary.
<telerikDataControls:RadListView.BindingContext>
<local:ViewModel />
</telerikDataControls:RadListView.BindingContext>
And we can also BindingContext like this(Any one is ok.):
BindingContext = new ViewModel();
The result is the same:

Resources