Xamarin Forms ListView Entry Field Transfer - xamarin.forms

I'm building an app that needs the Entry field a Button and a ListView, so when I type something in the entry field and click the button, the field entered passes to the List View.
Does anyone have an example that I can rely on?
Thanks in advance

so when I type something in the entry field and click the button, the field entered passes to the List View.
First , you can refer to this official document to create a ListView with Data binding.Then adding Button and Entry to layout,last you can deal with adding data by button click event.
The employee class:
public class Employee{
public string DisplayName {get; set;}
}
The DataModel Class:
public class DataModel
{
public ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
public DataModel()
{
employees.Add(new Employee { DisplayName = "Rob Finnerty" });
employees.Add(new Employee { DisplayName = "Bill Wrestler" });
employees.Add(new Employee { DisplayName = "Dr. Geri-Beth Hooper" });
employees.Add(new Employee { DisplayName = "Dr. Keith Joyce-Purdy" });
employees.Add(new Employee { DisplayName = "Sheri Spruce" });
employees.Add(new Employee { DisplayName = "Burt Indybrick" });
}
}
The following snippet demonstrates a ListView bound to a list of employees,adding Button and Entry.When clicking button,text from Entry will add to 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:local="clr-namespace:App1"
x:Class="App1.MainPage">
<StackLayout BackgroundColor="Gray">
<!-- Place new controls here -->
<Entry x:Name="EntryText" Placeholder="input"/>
<Button Text="click me"
HorizontalOptions="Center"
VerticalOptions="Center"
Clicked="OnButtonClicked"/>
<ListView x:Name="EmployeeView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding DisplayName}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Finally ContentPage will deal with Click Event:
DataModel dataModel;
public MainPage()
{
InitializeComponent();
dataModel = new DataModel();
EmployeeView.ItemsSource = dataModel.employees;
}
void OnButtonClicked(object sender, EventArgs args)
{
Console.WriteLine("click me");
dataModel.employees.Add(new Employee { DisplayName = EntryText.Text });
}

Related

ViewCell execue command from ViewModel

I want to bind my MenuItem from my ViewCell which has a ViewModel.
This is my View cell, Do any one know the proper way do this type of binding?
I have an ObservableCollection<object> that populate my ListView, this the cell I need to bind.
<?xml version="1.0" encoding="UTF-8" ?>
<ViewCell
x:Class="DataTemp.Controls.DeviceViewCell"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="this">
<ViewCell.ContextActions>
// I've been trying these two ways
<MenuItem Command="{Binding Source={x:Reference this}, Path=BindingContext.DeviceCommand}" Text="Call" />
<MenuItem Command="{Binding DeviceCommand}" Text="Call" />
</ViewCell.ContextActions>
<ViewCell.View>
<StackLayout Padding="10">
<Label Text="{Binding Name}" />
<Label Text="{Binding Number}" />
</StackLayout>
</ViewCell.View>
</ViewCell>
Here is my view model
I'm trying to catch the event with a a breakpoint, but i never get into the method OnDeviceCommnad.
public class DeviceViewCellViewModel : BaseViewModel, IDevice
{
public string Number
{
get
{
return _numberDevice;
}
set
{
_numberDevice = value;
OnPropertyChanged("Number");
}
}
public string Name
{
get
{
return _nameDevice;
}
set
{
_nameDevice = value;
OnPropertyChanged("Number");
}
}
public ICommand DeviceCommand { get; set; }
private string _nameDevice;
private string _numberDevice;
public DeviceViewCellViewModel()
{
DeviceCommand = new Command(OnDeviceCommnad);
}
private void OnDeviceCommnad()
{
}
}
If you not need to pass a parameter, the second way should work.
<MenuItem Command="{Binding DeviceCommand}" Text="Call" />
And in Model sample code could as follows:
public Command DeviceCommand { get; private set; }
public DeviceViewCellViewModel()
{
DeviceCommand = new Command(() =>
{
// Execute logic here
});
}
=============================Update==================================
From shared sample, I found that the binded MainViewModel not using DeviceViewCellViewModel, therefore the command will not be invoked.
Modify the folloing code inside MainViewModel:
PaymentsAndDevices.Add(new Devices()
{
Number = rdn.Next().ToString(),
Name = "I'm a device"
});
as follows:
PaymentsAndDevices.Add(new DeviceViewCellViewModel()
{
Number = rdn.Next().ToString(),
Name = "I'm a device"
});
Then OnDeviceCommnad method will be invoked.

Adding data to CarouselView item source results in error

I have a Xamarin CarouselView initialized with an empty ObservableCollection. The Carousel view correctly shows the EmptyView on page load.
However, when I add an item to the Observable Collection iOS throws the following exception:
attempt to insert item 0 into section 0, but there are only 0 items in section 0 after the update
The way I'm populating the item source is after the page loads I've hooked a button to an event handler to add items to the Observable Collection.
If I initialize the Observable Collection with initial data then the CarouselView works fine, it's just when I add items later that it breaks.
Page:
...
<ContentPage.BindingContext>
<viewModel:MatchesPageViewModel></viewModel:MatchesPageViewModel>
</ContentPage.BindingContext>
<CarouselView Margin="-10,15,-10,0"
ItemsSource="{Binding PendingMatches}"
HorizontalOptions="FillAndExpand"
HorizontalScrollBarVisibility="Never"
IsSwipeEnabled="True"
VerticalOptions="StartAndExpand">
<CarouselView.EmptyView>
<Frame>
<Label Text="It's empty"></Label>
</Frame>
</CarouselView.EmptyView>
<CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="Some Content"></Label>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
View Model:
public class MatchesPageViewModel : BaseViewModel
{
public ObservableCollection<MatchResponse> PendingMatches { get; set; } =
new ObservableCollection<MatchResponse>();
//pretend it's invoked from a button in the page
public void SomeEventHandler()
{
//throws exception: attempt to insert item 0 into section 0...
PendingMatches.Add(new MatchResponse());
}
}
I guess that you may have some problem about adding item in observablecollection for Button click method. I do one demo using Button command binding that you can take a look.
<CarouselView
HorizontalOptions="FillAndExpand"
HorizontalScrollBarVisibility="Never"
IsSwipeEnabled="True"
ItemsSource="{Binding PendingMatches}"
VerticalOptions="StartAndExpand">
<CarouselView.EmptyView>
<Frame>
<Label Text="It's empty" />
</Frame>
</CarouselView.EmptyView>
<CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding str}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Button
x:Name="btn1"
Command="{Binding command1}"
Text="add data" />
public partial class Page2 : ContentPage
{
public Page2()
{
InitializeComponent();
this.BindingContext = new MatchesPageViewModel();
}
}
public class MatchesPageViewModel
{
public ObservableCollection<MatchResponse> PendingMatches { get; set; } = new ObservableCollection<MatchResponse>();
public ICommand command1 { get; set; }
public MatchesPageViewModel()
{
command1 = new Command(SomeEventHandler);
}
public void SomeEventHandler()
{
//throws exception: attempt to insert item 0 into section 0...
PendingMatches.Add(new MatchResponse() { str = "test" });
}
}
public class MatchResponse
{
public string str { get; set; }
}

Trying to pass data to View (contains ListView) and set it as content

I have a List of strings in my main page,
which I want to pass to another view. The attribute,
to whom I writing to has a binding. Essentially it's
the ItemSource of the ListView.
I tried additionally to List, both string[] and ObservableCollection as data storage
for Projects, since the documentation recommends to use it.
Trying to use the -element from MyView.xaml in MainPage.xaml works like charm.
MainPage.xaml:
Content = new MyView { Projects = MyProjects };
MyView.xaml.cs:
public partial class MyView : ContentView
{
private List<string> _projects;
public List<string> Projects
{
get => _projects;
set
{
_projects = value;
OnPropertyChanged(nameof(Projects));
}
}
//public string[] Test = new string[] { "Test", "Hallo", "Welt" };
public MyView ()
{
InitializeComponent();
}
}
MyView.xaml:
<StackLayout>
<ListView BackgroundColor="Red" x:Name="p_lstView" RowHeight="160" SeparatorColor="DodgerBlue" ItemsSource="{Binding Projects}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
You have some issues with the BindingContext on the ListView.ItemSource. The current context is on the MainPage.
You need to change:
<ListView BackgroundColor="Red" x:Name="p_lstView" RowHeight="160" SeparatorColor="DodgerBlue" ItemsSource="{Binding Content.Projects}">
Alternative, you can set the BindingContext in the MyView constrctor.
You should set the BindingContext then the binding will work:
public MyView()
{
InitializeComponent();
BindingContext = this;
}

Binding data to a listview and hiding a field

I have the code below in the constructor of my .cs file of a page. I am able to pull
data without a problem
void InitData()
{
ArticlesService objArtServ = new ArticlesService();
Task<List<ArticlesModel>> dataRetrieved = objArtServ.GetValues("News");
//Bind headlines and Id to listview but hide Id
// datalist.itemsource = ?
}
Here is the service that returns the data for me without any problem.
public class ArticlesService
{
HttpClient client;
public async Task<List<ArticlesModel>> GetValues(string category){
client = new HttpClient();
var response = await client.GetStringAsync("http://testing-dev.com/Api/Articles/DefaultArticles/" + category);
var articlesModel = JsonConvert.DeserializeObject<List<ArticlesModel>>(response);
return articlesModel;
}
}
I have a grid on this main page and a list view which will list the headlines from my model and Id. The id will be hidden
and not displayed on the list.
Here is the code below
<StackLayout Grid.Column="1" Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="0" Spacing="0">
<SearchBar x:Name="searchBar" Placeholder="Search" SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"/>
<StackLayout VerticalOptions="FillAndExpand">
<StackLayout VerticalOptions="FillAndExpand" Padding="1" BackgroundColor="Black">
<ListView x:Name="dataList" BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label FontSize="20" VerticalOptions="CenterAndExpand" TextColor="Black" Text="{Binding HeadLines}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
Here is my model I am using
public class ArticlesModel
{
public Int32 Id { get; set; }
public string HeadLines { get; set; }
public string Url { get; set; }
public string Category { get; set; }
public string Summary { get; set; }
}
Questions
How do I bind only the HeadLines and Id to my listview such that my Id will be hidden but the headlines will show in the listview
On the click of each row in my listview, I want to be able to pass the associated Id so I can use the Id to query my list for other things.
How do I achieve this?
You don't need to bind the id if you're not displaying it. The ItemSelected event will pass you the complete ArticlesModel object for the row that was tapped, and you can easily get the ID from the model.
dataList.ItemSelected += (s,e) {
if (e.SelectedItem == null) return;
// item will be a pointer to the selected ArticlesModel object
var item = (ArticlesModel)e.SelectedItem;
// then you can use item.Id or any other property on ArticlesModel
};

xamarin forms FlowListView not showing data from List

I have a FlowListView control that is not displaying the items from a list. For test purposes I just wanted to display file path of the photo as a label.
Here is the xaml code:
<?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:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms.Controls"
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
x:Class="TamarianApp.ImagePage">
<ContentPage.Content>
<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="true" x:Name="image_gallary" ItemsSource="{Binding photos}" HeightRequest="100" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Label Text="{Binding filepath}" TextColor="Black" Margin="20" VerticalOptions="Fill" HorizontalOptions="Fill" XAlign="Center" YAlign="Center"></Label>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
</ContentPage.Content>
</ContentPage>
Here is the backend:
public partial class ImagePage : ContentPage
{
public List<Photo> photos = App.rug.photos
public ImagePage()
{
InitializeComponent();
Title = "Photos";
}
}
'App.rug.photos' is a List of the Photo class which contains the string field 'filepath'. Debugging shows field 'photos' is not empty and contains the data from 'App.rug.photos.'
Please Help.
It may be to do with how you are assigning the list, you need to make sure that the list is a Property in order for the binding to work correctly.
Try..
public partial class ImagePage : ContentPage
{
public List<Photo> photos {get; set;}
public ImagePage()
{
InitializeComponent();
Title = "Photos";
photos = App.rug.photos
}
}
You may also need to set the binding context
public partial class ImagePage : ContentPage
{
public List<Photo> photos {get; set;};
public ImagePage()
{
InitializeComponent();
this.BindingContext = this;
Title = "Photos";
photos = App.rug.photos
}
}
Try this code.
public ObservableCollection<object>() photos;
...
var oc = new ObservableCollection<Photo>();
foreach (var item in App.rug.photos)
oc.Add(item);
photos = oc as ObservableCollection<object>;
I was having trouble with ObservableCollection<MyObject>, but solved it by using ObservableCollection<object>.

Resources