Reputation: 20279
I'm removing items from my ListView
. Because I also use a counter in the group header, I have to update it. But how can I do this? This is my code:
ListView
:
<ListView x:Name="MyListList"
HasUnevenRows="True"
CachingStrategy="RecycleElement"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding LoadDataCommand}"
IsRefreshing="{Binding IsRefreshing, Mode=OneWay}">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<customViews:MyGroupingHeaderCell/>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<customViews:MyHeaderCell />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Custom group header:
<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Views.MyGroupingHeaderCell"
xmlns:customViews="clr-namespace:Views;"
xmlns:renderer="clr-namespace:Common.CustomRenderers;">
<renderer:ListViewGroupHeader x:Name="keyName" Style="{StaticResource labelHeader}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ViewCell>
public partial class MyGroupingHeaderCell : ViewCell
{
public MyGroupingHeaderCell()
{
InitializeComponent();
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var item = BindingContext as ObservableGroupCollection<string, CustomObject>;
if (item != null)
{
this.keyName.Text = item.Key + " (" + item.Count + ")";
}
else
{
this.keyName.Text = string.Empty;
}
}
}
I create the Key
for the item with this LINQ expression
List<ObservableGroupCollection<string, CustomObject>> resultList = rawList.OrderByWithDirection(order, descending)
.GroupBy(group)
.Select(p => new ObservableGroupCollection<string, CustomObject>(p))
.OrderByWithDirection(i => i.Key, false) // sort the group
.ToList();
where group
is
Func<CustomObject, string> group = p => p.SomeObject.Identification;
Probable solution:
What I'm doing now is that I completely reload the ListView
by removing the item from the origin data and re-setting the ItemSource
. This is not a really perfomant solution, but it works. The advantage of an ObservableCollection
is gone though.
Upvotes: 0
Views: 785
Reputation: 13601
Assuming ObservableGroupCollection
implements INotifyCollectionChanged
- we can subscribe to collection change event. To do that it would be easier to add a bindable property as it is simpler to track property changes, and hence subscribe/unsubscribe from events.
public partial class MyGroupingHeaderCell : ViewCell
{
public static readonly BindableProperty CollectionProperty =
BindableProperty.Create(
"Collection", typeof(INotifyCollectionChanged), typeof(MyGroupingHeaderCell),
defaultValue: default(INotifyCollectionChanged), propertyChanged: OnCollectionChanged);
public INotifyCollectionChanged Collection
{
get { return (INotifyCollectionChanged)GetValue(CollectionProperty); }
set { SetValue(CollectionProperty, value); }
}
private static void OnCollectionChanged(BindableObject bindable, object oldValue, object newValue)
{
((MyGroupingHeaderCell)bindable).OnCollectionChangedImpl((INotifyCollectionChanged)oldValue, (INotifyCollectionChanged)newValue);
}
protected virtual void OnCollectionChangedImpl(INotifyCollectionChanged oldValue, INotifyCollectionChanged newValue)
{
if(oldValue != null)
oldValue.CollectionChanged -= OnCollectionChanged;
if(newValue != null)
newValue.CollectionChanged += OnCollectionChanged;
OnCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var item = BindingContext as ObservableGroupCollection<string, CustomObject>;
if (item != null)
{
this.keyName.Text = item.Key + " (" + item.Count + ")";
}
else
{
this.keyName.Text = string.Empty;
}
}
}
And, XAML usage will change to:
<ListView.ItemTemplate>
<DataTemplate>
<customViews:MyHeaderCell Collection="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
Upvotes: 1