Hi, this is about seperation of concerns and is about binding a listview item to a seperate viewmodel instead of the model itself. I was looking for a way to clean up my models that implemented a few properties only for presentation purpuses. Then I stumbled upon this post: "burkharts dot net slash apps slash blog slash advanced-listview-bindings" <- I am not yet allowed to post the source...
But maybe because I'm fairly new to Xamarin.Forms and startet learning with FreshMvvm I do not understand one or two points that are going on right here.
I hope it is ok if I cite the code passages.
So, instead of this common scenario where the model (dog listview item) is directly tied to the view
// viewmodel
[ImplementPropertyChanged] //I use Fody here to not have to bother with INotifyPropertyChanged
public class DemoListViewPageModel
{
public ObservableCollection<Dog> DogList
public DemoListViewPageModel()
{
DogList = new ObservableCollection<Dog>();
DogList.Add(new Dog() { Name = "Rex", Race = "German Sheppard" });
DogList.Add(new Dog() { Name = "Barney", Race = "Poodle" });
DogList.Add(new Dog() { Name = "Jimmy", Race = "Beagle" });
DogList.Add(new Dog() { Name = "Rob", Race = "Labrador" });
}
}
// model
// Should be something that makes a bit of sense, so why not dogs
[ImplementPropertyChanged]
public class Dogs
{
public string Name {get; set}
public string Race {get; set;}
}
// view
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="..."
xmlns:x="..."
x:Class="Examples.DemoListViewPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
<ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="Start" >
<Label x:Name="Name" Text="{Binding Name}" TextColor="Navy" FontSize="20"/>
<Label x:Name="Race" Text="{Binding Race}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
he recommends to introduce another viewmodel for the listview items like this:
// dog item viewmodel
public class DogsItemViewModel
{
private Dog DogObject;
ICommand AddToCartCommand;
public DogsItemViewModel(Dog theDog)
{
DogObject = theDog;
AddToCartCommand = new Xamarin.Forms.Command(AddToCart);
}
public string Name => DogObject.Name;
public string Race => DogObject.Race.ToUpper();
public bool IsChecked { get; set; }
void AddToCart()
{
WebService.Instance.AddToCart(DogObject); // Whatever this will do ;-)
}
}
// dog item view
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="..." xmlns:x="..."
x:Class="YourNameSpace.DogItemView">
<StackLayout HorizontalOptions="Start" >
<CheckBox State = "{Binding IsChecked}" />
<Label x:Name="Name" Text="{Binding Name}" TextColor="Navy" FontSize="20"/>
<Label x:Name="Race" Text="{Binding Race}"/>
<Button Text="Add to Cart" Command="{Binding AddToCartCommand}"/>
</StackLayout>
</ViewCell>
// listview pages view
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="..."
xmlns:x="..."
x:Class="Examples.DemoListViewPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
<ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<DogItemView BindingContext = "{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
First of all: Does this line mean
<DogItemView BindingContext = "{Binding}" />
that the path of the binding context is set to Path=. which means it set to DogsItemViewModel()?
If so, how is the constructor of DogsItemViewModel called with the listview item from DogList?
Is there any other approach you could recommend to stop pulluting the model with view-bound properties?