How to delete item from ListView in Xamarin forms - xamarin

I have a ListView and I want to delete some items, I have not found a useful answer yet.
this is a XMAL :
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding Name}"
Style="{DynamicResource ListItemTextStyle}" />
<Label Text="{Binding PhoneNo}"
Style="{DynamicResource ListItemDetailTextStyle}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and listview :
public ObservableCollection<Contact> ContactList2 { get; set; }
I can easily add it, but I do not know how to delete it.

Use a context menu
XAML
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
code behind
public void OnDelete (object sender, EventArgs e) {
var mi = ((MenuItem)sender);
Contact contact = (Contact)mi.CommandParameter;
ContactList2.Remove(contact);
}

Related

Xamarin: CollectionView columns to trigger different actions

I have this in XAML:
<CollectionView ItemsSource="{Binding Accepted}"
SelectionMode="Single" SelectionChanged="OnAcceptedSelected">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding friendlyname}"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And this is the OnClick handler:
async void OnAcceptedSelected(object sender, SelectionChangedEventArgs e) {
MyItem selectedMI = e.CurrentSelection.FirstOrDefault() as MyItem;
// do something
}
I want to be able to do different things with selectedMI depending on what column the user clicked on, something like this:
<CollectionView ItemsSource="{Binding Accepted}"
SelectionMode="Single" SelectionChanged="OnAcceptedSelected">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding friendlyname}"/>
<Label x:Name="Action_A" />
<Label x:Name="Action_B" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
so that I could do something like this:
async void OnAcceptedSelected(object sender, SelectionChangedEventArgs e) {
MyItem selectedMI = e.CurrentSelection.FirstOrDefault() as MyItem;
// if clicked on Action_A do something and
// if clicked on Action_B do something else
}
Xamarin doesn't seem to offer an obvious way to do that. Any ideas how to implement this functionality?
Thanks.
Adding gesture to Label is a good choice.
I wrote a small example for your reference.
Two labels are added to each row of the CollectionView, and two events are respectively bound. Clicking on a different label will enter two different methods, and you can get the information of the label you clicked inside the method.
Here is the xaml code:
<CollectionView ItemsSource="{Binding Accepted}" >
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" BackgroundColor="Red" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="tapCommand"/>
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding .}" BackgroundColor="blue" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="tapCommand1"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Here is the background code:
public partial class MainPage : ContentPage
{
public ObservableCollection<string> Accepted { get; set; }
public MainPage()
{
Accepted = new ObservableCollection<string>();
Accepted.Add("aaa");
Accepted.Add("bbb");
Accepted.Add("ccc");//Simulation data
InitializeComponent();
BindingContext = this;
}
private void tapCommand(object sender, EventArgs e)//event1
{
string res = (sender as Label).Text;
}
private void tapCommand1(object sender, EventArgs e)//event2
{
string res = (sender as Label).Text;
}
}

ViewCell repeated many times in Listview Xamarin

I have
Test.xaml
<ContentPage.Content>
<StackLayout>
<ListView x:Name="myCarts" HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label TextColor="#848484" Text="11" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
Test.xaml.cs
public Test()
{
InitializeComponent();
var cartUserInfo = Preferences.Get("CartUser", "defaultcart");
myCarts.ItemsSource = cartUserInfo;
}
I checked the data in cartUserInfo Preferences only 1 line of data. Why does it repeat again in the UI?
How does it display correctly. Thank you

Grouped ListView throws Index Out of Range exception when clicking outside of list in xamarin forms wpf

I have face issue with grouped listview in xamarin forms wpf application. I have used group listview in one of the pages in the application, where if I click outside of the grouped listview, the application is crashed. Please suggest any idea to fix this crash. Thank you.
exception : An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
Index was out of range. Must be non-negative and less than the size of the collection.
Image :
SampleCode :
Xaml :
<StackLayout HorizontalOptions = "FillAndExpand" VerticalOptions = "FillAndExpand">
<ListView x:Name="GroupedViewM" IsGroupingEnabled="true" ItemsSource="{Binding All}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemTapped="SelectedUserorChannel">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="0,0,0,10">
<Label Text="{Binding Title}" TextColor="#e0e2e5" FontSize="22" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
<Image x:Name="AddButton" IsVisible="{Binding AddChannelBtnVisibility}" Source="add.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand" Margin="0,0,10,0">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="CreateNewChannel"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image Source="{Binding ProfileImage}" HorizontalOptions="Start" VerticalOptions="FillAndExpand" HeightRequest="20" WidthRequest="20"/>
<Label Text="{Binding FirstName}" TextColor="#e0e2e5" FontSize="Small" HorizontalOptions="FillAndExpand" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand"/>
<Frame CornerRadius="5" BackgroundColor="#5e997c" Padding="8,0" IsVisible="{Binding MessageCountVisibility}" HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="{Binding MessageCount}" TextColor="White" FontSize="15" HorizontalOptions="Center" VerticalOptions="Center"/>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Xaml.cs
private void SelectedUserorChannel(object sender, ItemTappedEventArgs e)
{
try
{
var userModel = ((ListView)sender).SelectedItem as UserModel;
OpenUserOrGroupChat(userModel);
((ListView)sender).SelectedItem = null;
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}
private async void CreateNewChannel(object sender, EventArgs e)
{
try
{
await Helper.NavigateToAsync(new CreateChannelView());
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}`
Probably you are casting null with some datatype say UserModel.
i would suggest you to refactor your code with a null check in place
{
if (((ListView)sender).SelectedItem != null && ((ListView)sender).SelectedItem as UserModel userModel)
{
OpenUserOrGroupChat(userModel);
((ListView)sender).SelectedItem = null;
}
}
Try this setting Footer property of this ListView as:
<ListView x:Name="GroupedViewM" IsGroupingEnabled="true"
ItemsSource="{Binding All}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemTapped="SelectedUserorChannel"
Footer="">
</ListView>

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());
}
}

Xamarin - how to open a new ContentPage in a ListView?

I have a list that comes from my web service and i display it like so:
<StackLayout HorizontalOptions="FillAndExpand">
<ListView x:Name="curso" ItemSelected="CursoView_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<Label StyleClass="Header" Text="{Binding name}" />
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
And now i want to be able to click on an item and open a new ContentPage
public void CursoView_ItemSelected(object sender, ItemSelectedEventArgs e)
{
// this assumes your current page is already contained in a NavigationPage
Navigation.PushAsync(new MyNextPage());
}

Resources