Reputation: 3071
I have a listview with a label and an image created using taplate viewcell. On tap of an image I would like to redirect to new page say page B and display details of item tapped.
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using Xamarin.Forms;
namespace ____
{
public class SelectMultipleBasePage<T> : ContentPage
{
public class WrappedSelection<T> : INotifyPropertyChanged
{
public T Item { get; set; }
bool isSelected = false;
public bool IsSelected
{
get
{
return isSelected;
}
set
{
if (isSelected != value)
{
isSelected = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
// PropertyChanged (this, new PropertyChangedEventArgs (nameof (IsSelected))); // C# 6
}
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
public class BackGroundColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool)
{
if ((bool)value)
{
return Color.FromHex("#DEE4EA");
}
else
{
return Color.White;
}
}
else
{
return Color.White;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class WrappedItemSelectionTemplate : ViewCell
{
public WrappedItemSelectionTemplate()
: base()
{
Grid objGrid = new Grid();
objGrid.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
});
objGrid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(75, GridUnitType.Absolute),
});
objGrid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Star)
});
objGrid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = GridLength.Auto
});
//
// Column 1:-
Image objImage = new Image();
objImage.SetBinding(Image.SourceProperty, new Binding("Item.Image"));
objGrid.Children.Add(objImage, 0, 0);
// Column 2:-
StackLayout objStackLayoutCol2 = new StackLayout();
objGrid.Children.Add(objStackLayoutCol2, 1, 0);
Label name = new Label()
{
Text = "Name",
Style = (Style)Application.Current.Resources["LabelStyle"],
};
Label date = new Label()
{
Text = "Date",
Style = (Style)Application.Current.Resources["LabelStyleTiny"]
};
name.SetBinding(Label.TextProperty, new Binding("Item.Name"));
date.SetBinding(Label.TextProperty, new Binding("Item.Date"));
objStackLayoutCol2.Children.Add(name);
objStackLayoutCol2.Children.Add(date);
objStackLayoutCol2.Padding = new Thickness(10);
Image objImageView = new Image();
objImageView.GestureRecognizers.Add(new TapGestureRecognizer(OnTap));
objImageView.Source = ImageSource.FromFile("Search.png");
objGrid.Children.Add(objImageView, 2, 0);
objGrid.SetBinding(Grid.BackgroundColorProperty, "IsSelected", converter: new BackGroundColorConverter());
//
// define context actions
//
var moreAction = new MenuItem { Text = "More" };
moreAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
moreAction.Clicked += (sender, e) =>
{
var mi = ((MenuItem)sender);
//Debug.WriteLine("More Context Action clicked: " + mi.CommandParameter);
};
var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.Icon = Device.OnPlatform("Icons/cancel.png", "cancel.png", "Images/cancel.png");
deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
deleteAction.Clicked += (sender, e) =>
{
var mi = ((MenuItem)sender);
//Debug.WriteLine("Delete Context Action clicked: " + mi.CommandParameter);
};
//
// add context actions to the cell
//
ContextActions.Add(moreAction);
ContextActions.Add(deleteAction);
//objGrid.Padding = new Thickness(10);
StackLayout st = new StackLayout();
st.Children.Add(objGrid);
st.Children.Add(new BoxView() { Color = Color.FromHex("#A4B3C1"), WidthRequest = 100, HeightRequest = 1 });
View = st;
}
public static void OnTap(View obj)
{
List<T> test= GetSelection();
MessagingCenter.Send(new RedirectClass.OpenRecordingDetails(), RedirectClass.OpenRecordingDetails.Key);
}
}
public static List<WrappedSelection<T>> WrappedItems = new List<WrappedSelection<T>>();
public SelectMultipleBasePage(List<T> items)
{
WrappedItems = items.Select(item => new WrappedSelection<T>() { Item = item, IsSelected = false }).ToList();
ListView mainList = new ListView()
{
ItemsSource = WrappedItems,
ItemTemplate = new DataTemplate(typeof(WrappedItemSelectionTemplate)),
};
mainList.ItemSelected += (sender, e) =>
{
if (e.SelectedItem == null) return;
var o = (WrappedSelection<T>)e.SelectedItem;
o.IsSelected = !o.IsSelected;
((ListView)sender).SelectedItem = null; //de-select
};
Content = mainList;
mainList.HasUnevenRows = true;
if (Device.OS == TargetPlatform.WinPhone)
{ // fix issue where rows are badly sized (as tall as the screen) on WinPhone8.1
mainList.RowHeight = 40;
// also need icons for Windows app bar (other platforms can just use text)
ToolbarItems.Add(new ToolbarItem("All", "check.png", SelectAll, ToolbarItemOrder.Primary));
ToolbarItems.Add(new ToolbarItem("None", "cancel.png", SelectNone, ToolbarItemOrder.Primary));
}
else
{
// mainList.MinimumHeightRequest = 80;
// mainList.RowHeight = 80;
ToolbarItems.Add(new ToolbarItem("All", null, SelectAll, ToolbarItemOrder.Primary));
ToolbarItems.Add(new ToolbarItem("None", null, SelectNone, ToolbarItemOrder.Primary));
}
}
void SelectAll()
{
foreach (var wi in WrappedItems)
{
wi.IsSelected = true;
}
}
void SelectNone()
{
foreach (var wi in WrappedItems)
{
wi.IsSelected = false;
}
}
public static List<T> GetSelection()
{
return WrappedItems.Where(item => item.IsSelected).Select(wrappedItem => wrappedItem.Item).ToList();
}
}
}
I tried adding a GestureRecognizers ontap but getselection returns the list of items if the listview is clicked anywhere other then a image.
Any help?
Edit
I also tried adding something like this:
Button aButton = new Button { Text = "TestButton" };
aButton.SetBinding(Button.CommandParameterProperty, new Binding("Item.Name"));
aButton.Command = new Command<Button>((Button theCellItem) =>
{
var s = theCellItem.ToString();
//DisplayAlert("Tadaa", theCellItem.ToString(), "Ok");
});
But It doesn't work. Getting error:
System.InvalidCastException: Specified cast is not valid.
Upvotes: 0
Views: 6201
Reputation: 13
If you use a ListView ItemTemplate containing your control, user can click anywhere on the item (which seems more convenient).
The sender is then your ListView so you may try this:
ListView listView = sender as ListView;
Person selectedItem = listView == null ? null : listView.SelectedItem as Person;
Upvotes: 0
Reputation: 459
Use the ListView's EventHandler for ItemTapped then on codebehind you should be able to access the item by casting the object parameter to the expected type from your ListView.
private void MyListView_OnItemTapped(object sender, ItemTappedEventArgs e)
{
var person = sender as Person;
Debug.WriteLine($"His name was {person.Name}");
}
Upvotes: 0
Reputation: 1197
You can disable the list view selection by setting isEnabled property to false .This will make listview unclickable while GestureRecognizers on ViewCell will respond as expected
For Navigation this can be of help
Upvotes: 1