CollectionView with ObservableRangeCollection not updating data change - xamarin

I want to change the data of one object in my ObservableRangeCollection, and that works but the corresponding 'CollectionView` does not update the changed data.
'CollectionView`
<RefreshView Grid.Row="1"
Grid.RowSpan="2"
Command="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy, Mode=OneWay}">
<CollectionView x:Name="Collection"
ItemsSource="{Binding Locations}"
SelectionMode="Single"
BackgroundColor="Transparent"
ItemsLayout="VerticalList">
<CollectionView.EmptyView>
<StackLayout Padding="12">
<Label HorizontalOptions="Center" Text="Keine Daten vorhanden!" TextColor="White"/>
</StackLayout>
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:MainModel">
<Frame HeightRequest="260">
<Grid>
<Image Source="{Binding Image}"
Aspect="AspectFill"/>
<Label Text="{Binding Name}"
FontSize="30"
TextColor="White"/>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
ViewModel
public class MainViewModel : VeiwModelBase
{
public ObservableRangeCollection<MainModel> Locations { get; set; } = new ObservableRangeCollection<MainModel>();
public ICommand RefreshCommand { get; }
public MainViewModel()
{
RefreshCommand = new AsyncCommand(Refresh);
}
public override void VModelActive(Page sender, EventArgs eventArgs)
{
base.VModelActive(sender, eventArgs);
var locs = new MainModel() { Image = "https://club-l1.de/wp-content/uploads/2019/11/dsc08645-1200x800.jpg", Name = "Test" };
Locations.Add(locs);
foreach (MainModel loc in Locations)
{
loc.Name = "Update";
}
}
private async Task Refresh()
{
IsBusy = true;
var locs = new MainModel() { Image = "https://club-l1.de/wp-content/uploads/2019/11/dsc08645-1200x800.jpg", Name = "Test"};
Locations.Add(locs);
foreach (MainModel loc in Locations)
{
loc.Name = "Update";
}
IsBusy = false;
}
}
The Project: https://github.com/Crey443/CollectionViewUpdate

MainModel needs to implement INotifyPropertyChanged, and any properties you want to bind (ie, Name) need to call PropertyChanged in their setters
public class MainModel
{
public string Name { get; set; }
public string Image { get; set; }
}

Related

How to mark the checkbox in repeater in Xamarin.Forms?

I am using checkbox control under repeater to do a radio button functionality, everything seems to be fine but now stuck on how to bind the checkbox when the page loads. I have saved the radio button text whichever was selected and once user come back to page again I want to bin what he has selected last time. Not getting any hint here how to proceed.
<grial:Repeater
x:Name="PP"
SelectionMode="Single"
InitialSelection="Empty"
ItemSize="100"
HorizontalOptions="Start"
ItemsSource="{Binding BlowerPostions}">
<grial:Repeater.ItemTemplate>
<DataTemplate>
<grial:Checkbox
IsChecked="false"
UncheckedBorderColor="Black">
<Label
TextColor="Black"
Text="{ Binding . }"
Margin="8,0" />
</grial:Checkbox>
</DataTemplate>
</grial:Repeater.ItemTemplate>
<grial:Repeater.SelectedItemTemplate>
<DataTemplate>
<grial:Checkbox
IsChecked="true"
UncheckedBorderColor="Black"
InputTransparent="true">
<Label
TextColor="Black"
Text="{ Binding . }"
Margin="8,0" />
</grial:Checkbox>
</DataTemplate>
</grial:Repeater.SelectedItemTemplate>
</grial:Repeater>
View Model :
public class ProductionViewModel : INotifyPropertyChanged
{
public ObservableCollection<BlowerPostion> _blowerPostions;
public ObservableCollection<BlowerPostion> BlowerPostions
{
get => _blowerPostions;
set
{
_blowerPostions = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs("BlowerPostions"));
}
}
}
public void LoadData()
{
BlowerPostions = new ObservableCollection<BlowerPostion>();
BlowerPostions.Add(new BlowerPostion("Left", 1));
BlowerPostions.Add(new BlowerPostion("Standard", 1));
}
}
public class BlowerPostion
{
public string Text { get; set; }
public int Id { get; set; }
public BlowerPostion(string _text, int _id)
{
Text = _text;
Id = _id;
}
}
I don't use grial:Repeater,but you can refer to the following code which use CheckBox in ListView item.
Item.cs
public class Item
{
public string Name { get; set; }
public string Type { get; set; }
public string Image { get; set; }
//This field indicates whether or not it is selected
public bool isChecked { get; set; }
}
MyViewModel.cs
public class MyViewModel
{
public ObservableCollection<Item> items { get; private set; }
public MyViewModel() {
items = new ObservableCollection<Item>();
items.Add(new Item { Name = "Tomato", Type = "Fruit", Image = "tomato.png", isChecked = true });
items.Add(new Item { Name = "Romaine Lettuce", Type = "Vegetable", Image = "lettuce.png", isChecked = false });
items.Add(new Item { Name = "Zucchini", Type = "Vegetable", Image = "zucchini.png", isChecked = false });
}
}
TestPage1.xaml
<ContentPage.Content>
<ListView x:Name="listview" ItemsSource="{Binding items}" VerticalOptions="FillAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="5,0,5,0">
<Label Text="{Binding Name}" HorizontalOptions="StartAndExpand" FontSize="30"/>
<input:CheckBox IsChecked="{Binding isChecked}" Type="Check" Color="White" BoxBackgroundColor="Green" TextColor="White" HeightRequest="40"
CheckChanged="CheckBox_CheckChanged" BindingContext="{Binding .}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
TestPage1.xaml.cs
public partial class TestPage1 : ContentPage
{
public List<Item> selectedItems; // define `selectedItems` as the list of selected items.
public MyViewModel viewModel;
public TestPage1 ()
{
InitializeComponent ();
selectedItems = new List<Item>(); // init the `selectedItems`
viewModel = new MyViewModel();
BindingContext = viewModel;
}
private void CheckBox_CheckChanged(object sender, EventArgs e)
{
var checkbox = (Plugin.InputKit.Shared.Controls.CheckBox)sender;
var ob = checkbox.BindingContext as Item;
if (ob != null)
{
System.Diagnostics.Debug.WriteLine("isChecked = " + ob.isChecked + "<---> Name = " + ob.Name +"<---> Type = " + ob.Type );
if (ob.isChecked)
{
selectedItems.Add(ob);
}
else {
// remove the item
}
}
}
}
Note:
1.add new field isChecked in item model
public bool isChecked { get; set; }
2.Add event CheckChanged for the item.And when we check the CheckBox,we can get the corresponding value isChecked of the CheckBox.
<input:CheckBox IsChecked="{Binding isChecked}" Type="Check" Color="White" BoxBackgroundColor="Green" TextColor="White" HeightRequest="40"
CheckChanged="CheckBox_CheckChanged" BindingContext="{Binding .}" />

Data binding for listview in xamarin

I am trying to populate listview with database table in xamarin forms app
I am getting null pointer exception
Below is XAML for listview
<ListView x:Name="_listView"
ItemsSource="{Binding itemsInList}"
Grid.Column="0"
Grid.Row="0"
SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0" />
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Below is xaml.cs(code behind)
public List <ServiceProvider> itemlist;
public List <ServiceProvider> itemsInList
{
get {return itemlist;}
}
protected override void OnAppearing()
{
base.OnAppearing();
ExpensesDatabase dbcon = new ExpensesDatabase(completePath);
itemlist = dbcon.GetItems(completePath);
// _listView.ItemsSource = itemlist;
}
Below is db file
public class ExpensesDatabase
{
readonly SQLiteConnection database;
public ExpensesDatabase(string dbPath)
{
database = new SQLiteConnection(dbPath);
database.CreateTable < ServiceProvider > ();
}
public List < ServiceProvider > GetItems(string dbPath)
{
return database.Table < ServiceProvider > ().ToList();
}
}
Data is not displayed in listview
If you want the ListView to automatically update as items are added, removed and changed in the underlying list, you'll need to use an ObservableCollection. ObservableCollection is defined in System.Collections.ObjectModel and is just like List, except that it can notify ListView of any changes:
public ObservableCollection<ServiceProvider> itemsInList { get; set; }
Then make sure you have set the right bindingContext and initialized the ObservableCollection:
public MainPage()
{
InitializeComponent();
itemsInList = new ObservableCollection<ServiceProvider>();
BindingContext = this;
}
I write a sample to test and it works on my side, you can have a look at the full code:
public partial class MainPage : ContentPage
{
public ObservableCollection<ServiceProvider> itemsInList { get; set; }
public MainPage()
{
InitializeComponent();
itemsInList = new ObservableCollection<ServiceProvider>();
BindingContext = this;
}
protected override void OnAppearing()
{
base.OnAppearing();
itemsInList.Add(new ServiceProvider() { Name= "a"});
}
}
public class ServiceProvider : INotifyPropertyChanged
{
string name;
public event PropertyChangedEventHandler PropertyChanged;
public ServiceProvider()
{
}
public String Name
{
set
{
if (name != value)
{
name = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
get
{
return name;
}
}
}
Feel free to ask me any question if you still can't solve it.

How to move this Selected Item Changed Events from Pages into ViewModel?

I have this code for handling Item Selected on ListView and once selected will redirect to other page with an Id.
I can do this in Pages level BUT I want to move this to ViewModel. How do I do this?
ActivitiesPage.xaml:
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="TbSearch" Icon="search.png" Command="{Binding SearchBtnClicked}"></ToolbarItem>
<ToolbarItem x:Name="TbAdd" Icon="add.png" Command="{Binding AddBtnClicked}"></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<!--<ListView ItemsSource="{Binding Items}" CachingStrategy="RecycleElement" ItemSelected="LvActivities_ItemSelected">-->
<ListView ItemsSource="{Binding Items}" CachingStrategy="RecycleElement" SelectedItem="{Binding NameSelectedItem}">
<ListView.Behaviors>
<extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsBusy}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Grid Padding="5" IsVisible="{Binding IsBusy}">
<!-- Footer HeightRequest must be 0 when not visible -->
<Grid.Triggers>
<Trigger TargetType="Grid" Property="IsVisible" Value="False">
<Setter Property="HeightRequest" Value="0" />
</Trigger>
</Grid.Triggers>
<Label Text="Loading..." TextColor="Crimson" FontSize="Large"
VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
</ListView.Footer>
</ListView>
</ContentPage.Content>
ActivitiesPage.xaml.cs
public partial class ActivitiesPage : ContentPage
{
public ObservableCollection<Activity> Activities;
public ActivitiesPage ()
{
InitializeComponent();
BindingContext = new ActivityViewModel(Navigation);
}
private void LvActivities_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var selectedActivity = e.SelectedItem as Activity;
Navigation.PushAsync(new ActivityDetailPage(selectedActivity.Id));
}
}
ActivityViewModel.cs
public class ActivityViewModel : BaseViewModel
{
private const int PageSize = 10;
private int totalRecords;
private readonly ApiService apiService = new ApiService();
public InfiniteScrollCollection<Activity> Items { get; }
public INavigation Navigation { get; set; }
private bool _isBusy;
public bool IsBusy
{
get => _isBusy;
set
{
_isBusy = value;
OnPropertyChanged();
}
}
public ICommand SearchBtnClicked
{
protected set;
get;
}
public ICommand AddBtnClicked
{
protected set;
get;
}
public ActivityViewModel(INavigation navigation)
{
this.Navigation = navigation;
Items = new InfiniteScrollCollection<Activity>
{
OnLoadMore = async () =>
{
IsBusy = true;
int page = Items.Count / PageSize;
ActivityResult activityResult = await apiService.GetActivities("-CreatedDate", page+1, PageSize);
IsBusy = false;
return activityResult.Results;
},
OnCanLoadMore = () =>
{
return Items.Count < totalRecords;
}
};
DownloadDataAsync();
this.SearchBtnClicked = new Command(async () => await GotoSearchPage());
this.AddBtnClicked = new Command(async () => await GotoAddPage());
}
public async Task GotoSearchPage()
{
await Navigation.PushAsync(new ActivitySearchPage());
}
public async Task GotoAddPage()
{
await Navigation.PushAsync(new ActivityAddPage());
}
private async Task DownloadDataAsync()
{
ActivityResult items = await apiService.GetActivities("-CreatedDate", 1, PageSize);
totalRecords = items.Metadata.TotalRecords;
Items.AddRange(items.Results);
}
Create a SelectedItem property in the view model
private Activity selectedActivity = null;
public Activity SelectedItem {
get { return selectedActivity; }
set {
selectedActivity = value;
NotifyPropertyChanged(); //assumption here
if(selectedActivity != null) {
Navigation.PushAsync(new ActivityDetailPage(selectedActivity.Id));
}
}
}
that can be bound to the list view
<ListView ItemsSource="{Binding Items}"
CachingStrategy="RecycleElement"
SelectedItem="{Binding SelectedItem}">
<!-- ...omitted for brevity -->
</ListView>
This will allow the event handler to be removed from the View's code behind.

Xamarin Forms Frame not expanding with content

I'm new to Xamarin Forms, and I've met my first challenge. I want a Frame around my Stacklayout within a Listview. When the user selects an item in the Listview I want some controls to appear. This works fine without the Frame, but the Frame does not expand when the controls appear. How can I change or get around this behavior?
Code below.
XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MVVMTest"
x:Class="MVVMTest.MainPage">
<StackLayout>
<ListView HasUnevenRows="True" SelectedItem="{Binding SelectedViewItem, Mode=TwoWay}" ItemsSource="{Binding Items}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame BackgroundColor="White" BorderColor="Black">
<StackLayout>
<Label Text="{Binding Name}"></Label>
<Entry Text="{Binding Details}" IsVisible="{Binding ShowDetails}"></Entry>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
XAML.cs
namespace MVVMTest
{
public partial class MainPage : ContentPage
{
public MainPage()
{
BindingContext = new ViewModel()
{
Items = new List<ViewModelItem>()
{
new ViewModelItem()
{
Name = "Test",
Details = "details"
},
new ViewModelItem()
{
Name = "Test2",
Details = "details2"
}
}
};
InitializeComponent();
}
}
}
Model:
namespace MVVMTest
{
public class ViewModel : INotifyPropertyChanged
{
private ViewModelItem _selectedViewItem;
private List<ViewModelItem> _items;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ViewModelItem SelectedViewItem
{
get
{
return _selectedViewItem;
}
set
{
_selectedViewItem = value;
OnPropertyChanged();
if (value != null)
{
value.ShowDetails = !value.ShowDetails;
SelectedViewItem = null;
}
}
}
public List<ViewModelItem> Items
{
get
{
return _items;
}
set
{
_items = value;
OnPropertyChanged();
}
}
public ViewModel()
{
}
}
public class ViewModelItem : INotifyPropertyChanged
{
private bool _showDetails;
private string _details;
private string _name;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
public bool ShowDetails
{
get
{
return _showDetails;
}
set
{
_showDetails = value;
OnPropertyChanged();
}
}
public string Details
{
get
{
return _details;
}
set
{
_details = value;
OnPropertyChanged();
}
}
}
}
I ended up using the PropertyChanged event to react to when the ListView was displayed or hidden. In the eventhandler, I set the HeightRequest of the Frame and this forces it to resize itself.
Alternative solution/help can be found here:
https://forums.xamarin.com/discussion/comment/366577
XAML:
<StackLayout>
<ListView HasUnevenRows="True" SelectedItem="{Binding SelectedViewItem, Mode=TwoWay}" ItemsSource="{Binding Items}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame BackgroundColor="White" BorderColor="Black" Margin="2" Padding="2" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout>
<Label Text="{Binding Name}"></Label>
<ListView HasUnevenRows="True" Margin="2" ItemsSource="{Binding DetailObjects}" IsVisible="{Binding ShowDetails}" PropertyChanged="ListView_PropertyChanged">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Entry Text="{Binding Details}"></Entry>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Code behind:
public partial class MainPage : ContentPage
{
public MainPage()
{
BindingContext = new ViewModel()
{
Items = new List<ViewModelItem>()
{
new ViewModelItem()
{
Name = "Test",
DetailObjects = new List<ViewModelItemDetails>
{
new ViewModelItemDetails
{
Details = "details1"
},
new ViewModelItemDetails
{
Details = "details2"
}
}
},
new ViewModelItem()
{
Name = "Test2",
DetailObjects = new List<ViewModelItemDetails>
{
new ViewModelItemDetails
{
Details = "details1"
},
new ViewModelItemDetails
{
Details = "details2"
}
}
}
}
};
InitializeComponent();
}
private void ListView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (!(sender is ListView list)) return;
if (e.PropertyName == ListView.IsVisibleProperty.PropertyName)
{
Element parent = list;
Frame frame = null;
while (frame == null && parent != null)
{
if (parent is Frame) frame = parent as Frame;
parent = parent.Parent;
}
if (list.IsVisible)
{
list.HeightRequest = list.ItemsSource.Cast<ViewModelItemDetails>().Count() * 50;
if (frame != null) frame.HeightRequest = list.HeightRequest + 50;
}
else
{
if (frame != null) frame.HeightRequest = 50;
}
}
}
}

<ListView> of images - How open URL via TapGestureRecognizer?

How can we open a URL (via TapGestureRecognizer) that is bound to a of images?
My ListView's ItemsSource is _partners (type of List).
The Partner class has two properties - WebUrl and ImageUrl.
<ListView x:Name="partnersListView">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ImageCell ImageSource="{Binding ImageUrl}" Text="{Binding WebUrl}" />-->
<ViewCell>
<Image Source="{Binding ImageUrl}">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="Image_TapGestureRecognizer_Tapped" NumberOfTapsRequired="1" CommandParameter="{Binding .}" />
</Image.GestureRecognizers>
</Image>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The list is showing images only, and I would like the app to navigate to a web site when the user taps the image. However, the following code - unsurprisingly - doesn't work.
private void Image_TapGestureRecognizer_Tapped(object sender, System.EventArgs e)
{
var tappedMenuItem = sender as MenuItem;
var partner = tappedMenuItem.CommandParameter as Partner;
Device.OpenUri(new Uri(partner.WebUrl));
}
Any suggestions, please?
Please note:
I want to keep the TapGestureRecognizer in XAML - not in the code-behind.
Thank you.
Best way to tackle this problem, is to bind the SelectedItem of the ListView to a property on your page.
So in your View
<ListView SelectedItem="{Binding SelectedPartner}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Image Source="{Binding ImageUrl}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
And in the Code Behind
public Partner SelectedPartner
{
set
{
if (value != null)
Device.OpenUri(new System.Uri(value.WebUrl));
}
}
The list is showing images only, and I would like the app to navigate to a web site when the user taps the image. However, the following code - unsurprisingly - doesn't work.
CommandParameter is just for Command, you can't get it from a tap event handler. To accomplish your requirement, you can either use TappedCallback together with TappedCallbackParameter or use Command together with CommandParameter:
Method 1(TapppedCallback and TappedCallbackParameter):
Modify your Partner class to hold an Action<View,object>:
public class Partner
{
public Partner(string weburl, string imageurl)
{
this.WebUrl = weburl;
this.ImageUrl = imageurl;
}
public Partner(string weburl, string imageurl, Action<View, object> callback) : this(weburl, imageurl)
{
this.CallBack = callback;
}
public Action<View, object> CallBack { get; set; }
public string WebUrl { get; set; }
public string ImageUrl { get; set; }
}
In your code-behind, define a TappedCallback function like below and initialize the items source with the this function:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
List<Partner> list = new List<Partner>
{
new Partner("http://www.url.com","timg.jpg",TappedCallback),
new Partner("http://www.url.com","timg.jpg",TappedCallback),
new Partner("http://www.url.com","timg.jpg",TappedCallback),
new Partner("http://www.url.com","timg.jpg",TappedCallback),
new Partner("http://www.url.com","timg.jpg",TappedCallback),
new Partner("http://www.url.com","timg.jpg",TappedCallback)
};
partnersListView.ItemsSource = list;
}
private void TappedCallback(View sender,object param)
{
var Partner = param as Partner;
Device.OpenUri(new Uri(Partner.WebUrl));
}
}
Use TappedCallback in Xaml:
<ListView x:Name="partnersListView">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ImageCell ImageSource="{Binding ImageUrl}" Text="{Binding WebUrl}" />-->
<ViewCell>
<Image Source="{Binding ImageUrl}">
<Image.GestureRecognizers>
<TapGestureRecognizer TappedCallback="{Binding CallBack}" TappedCallbackParameter="{Binding .}" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Method 2(Command and CommandParameter):
Define an ICommand in your Partner class and constructor to accept ICommand:
public class Partner
{
public Partner(string weburl, string imageurl)
{
this.WebUrl = weburl;
this.ImageUrl = imageurl;
}
public Partner(string weburl, string imageurl, ICommand command) : this(weburl, imageurl)
{
this.TapCommand = command;
}
public string WebUrl { get; set; }
public string ImageUrl { get; set; }
public ICommand TapCommand { get; set; }
}
Create a MyCommand class to implement the ICommand interface :
public class MyCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
var Partner = parameter as Partner;
Device.OpenUri(new Uri(Partner.WebUrl));
}
}
In your code-behind initialize your items source with a new MyCommand object:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
List<Partner> list = new List<Partner>
{
new Partner("http://www.url.com","timg.jpg",new MyCommand()),
new Partner("http://www.url.com","timg.jpg",new MyCommand()),
new Partner("http://www.url.com","timg.jpg",new MyCommand()),
new Partner("http://www.url.com","timg.jpg",new MyCommand()),
new Partner("http://www.url.com","timg.jpg",new MyCommand()),
new Partner("http://www.url.com","timg.jpg",new MyCommand())
};
partnersListView.ItemsSource = list;
}
}
Use Command in Xaml:
<ListView x:Name="partnersListView">
<ListView.ItemTemplate>
<DataTemplate>
<!--<ImageCell ImageSource="{Binding ImageUrl}" Text="{Binding WebUrl}" />-->
<ViewCell>
<Image Source="{Binding ImageUrl}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" CommandParameter="{Binding .}" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Resources