Reputation: 1009
I'm tring to create an expandable listview and I'm following this example:
The problem is that I'm using Prism as MVVM framework, so I can't use an event, I'm using a Command. This is the code:
XAML:
<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="JDeliveryCP.Views.DocumentsPage"
x:Name="TheDocumentsPage">
<ContentPage.Content>
<ListView x:Name="lstDocuments" GroupDisplayBinding="{Binding Title}" RowHeight="75" IsGroupingEnabled="True" ItemsSource="{Binding ExpandedDocuments}" >
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" >
<ContentView>
<Grid x:Name="cell">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Title}"/>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding HeaderTappedCommand}" BindingContext="{Binding Source={x:Reference lstDocuments}, Path=BindingContext}"
CommandParameter="{Binding Source={x:Reference cell}, Path=BindingContext}" />
</ContentView.GestureRecognizers>
</Grid>
</ContentView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Description}" ImageSource="icon.png" Height="75" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
PageViewModel:
using JDeliveryCP.FEModels;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using Xamarin.Forms;
namespace JDeliveryCP.ViewModels
{
public class DocumentsPageViewModel : BindableBase, INotifyPropertyChanged
{
private ObservableCollection<DocumentGroupModel> _documents;
private ObservableCollection<DocumentGroupModel> _expandedDocuments;
private ICommand headerTappedCommand;
public ICommand HeaderTappedCommand
{
get { return headerTappedCommand; }
}
public ObservableCollection<DocumentGroupModel> Documents
{
get { return _documents; }
set { SetProperty(ref _documents, value); }
}
public ObservableCollection<DocumentGroupModel> ExpandedDocuments
{
get { return _expandedDocuments; }
set { SetProperty(ref _expandedDocuments, value); }
}
public DocumentsPageViewModel()
{
headerTappedCommand = new Command(HeaderTapped);
//TEST -START-
_documents = new ObservableCollection<DocumentGroupModel>
{
new DocumentGroupModel(897, "Cliente 1", false)
{
new DocumentModel { Description = "documento 1"},
new DocumentModel { Description = "documento 2"},
new DocumentModel { Description = "documento 3"}
},
new DocumentGroupModel(543, "Cliente 2", false)
{
new DocumentModel { Description = "documento 4"},
new DocumentModel { Description = "documento 5"}
}
};
//TEST -END-
UpdateListContent();
}
async void HeaderTapped(object sender, EventArgs args)
{
HeaderTapped(sender);
}
private void HeaderTapped(object sender)
{
DocumentGroupModel selected = ((DocumentGroupModel)(sender));
DocumentGroupModel found = _documents.FirstOrDefault(x => x.Id == selected.Id);
found.Expanded = !found.Expanded;
UpdateListContent();
OnPropertyChanged(new PropertyChangedEventArgs("Expanded"));
}
private void UpdateListContent()
{
_expandedDocuments = new ObservableCollection<DocumentGroupModel>();
foreach(DocumentGroupModel group in _documents)
{
DocumentGroupModel newGroup = new DocumentGroupModel(group.Id, group.Title, group.Expanded);
if (group.Expanded)
{
foreach(DocumentModel doc in group)
{
newGroup.Add(doc);
}
}
_expandedDocuments.Add(newGroup);
}
}
}
}
GROUP MODEL:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JDeliveryCP.FEModels
{
public class DocumentGroupModel : ObservableCollection<DocumentModel>, INotifyPropertyChanged
{
private bool _expanded;
public string Title { get; set; }
public int Id { get; set; }
public bool Expanded
{
get { return _expanded; }
set
{
if (_expanded != value)
{
_expanded = value;
OnPropertyChanged(new PropertyChangedEventArgs("Expanded"));
}
}
}
public DocumentGroupModel(int id, string title, bool expanded = true)
{
Id = id;
Title = title;
Expanded = expanded;
}
}
}
ITEM MODEL:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JDeliveryCP.FEModels
{
public class DocumentModel
{
public string Description { get; set; }
}
}
The Listview is correctly rendered and the tap command works, but it doesn't show rows of the tapped group, the layout doesn't change. I tried to debug the "HeaderTapped" method and the groups are correctly populated. I don't know if it can be a problem of widget refresh or problems of binding between row model and pageviewmodel.
Thanks for your help!
Upvotes: 3
Views: 1762
Reputation: 1009
I solved the problem myself.
I changed this:
private void HeaderTapped(object sender)
{
DocumentGroupModel selected = ((DocumentGroupModel)(sender));
DocumentGroupModel found = _documents.FirstOrDefault(x => x.Id == selected.Id);
found.Expanded = !found.Expanded;
UpdateListContent();
OnPropertyChanged(new PropertyChangedEventArgs("Expanded"));
}
with this:
private void HeaderTapped(object sender)
{
DocumentGroupModel selected = ((DocumentGroupModel)(sender));
DocumentGroupModel found = _documents.FirstOrDefault(x => x.Id == selected.Id);
found.Expanded = !found.Expanded;
UpdateListContent();
OnPropertyChanged(new PropertyChangedEventArgs("ExpandedDocuments"));
}
So I changed only the "OnPropertyChanged" argument.
Upvotes: 1