Skip to content

Commit

Permalink
Start adding support for invalidating specific items
Browse files Browse the repository at this point in the history
This will help with 'resetting' an item if you change a property such that you expect it to change the size of the cell.
  • Loading branch information
Redth committed Apr 20, 2024
1 parent 245a2d6 commit df31f04
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 13 deletions.
16 changes: 15 additions & 1 deletion Sample/VirtualListViewSample/Section.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
namespace VirtualListViewSample;

public class Section : List<string>
public class Section : List<Item>
{
public string Title { get; set; }
}


public class Item : BindableObject
{

public static readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name), typeof(string), typeof(Item), string.Empty);

public string Name
{
get => (string)GetValue(NameProperty);
set => SetValue(NameProperty, value);
}
}
18 changes: 15 additions & 3 deletions Sample/VirtualListViewSample/SectionedAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace VirtualListViewSample;

public class SectionedAdapter : VirtualListViewAdapterBase<Section, string>
public class SectionedAdapter : VirtualListViewAdapterBase<Section, Item>
{
public SectionedAdapter(IList<Section> items) : base()
{
Expand All @@ -20,7 +20,7 @@ public override int GetNumberOfSections()
public override int GetNumberOfItemsInSection(int sectionIndex)
=> Items[sectionIndex].Count;

public override string GetItem(int sectionIndex, int itemIndex)
public override Item GetItem(int sectionIndex, int itemIndex)
=> Items[sectionIndex][itemIndex];

public void AddItem(string sectionTitle, string itemName)
Expand All @@ -33,7 +33,7 @@ public void AddItem(string sectionTitle, string itemName)
Items.Add(section);
}

section.Add(itemName);
section.Add(new Item { Name = itemName });
InvalidateData();
}

Expand All @@ -51,4 +51,16 @@ public void RemoveItem(int sectionIndex, int itemIndex)

InvalidateData();
}

public void UpdateItem(int sectionIndex, int itemIndex)
{
var section = Items.ElementAtOrDefault(sectionIndex);

if (section is null)
return;

section[itemIndex].Name = $"{section[itemIndex].Name} Updated";

InvalidateItems(new ItemPosition(sectionIndex, itemIndex));
}
}
21 changes: 13 additions & 8 deletions Sample/VirtualListViewSample/SectionedAdapterPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@
</DataTemplate>
</vlv:VirtualListView.SectionHeaderTemplate>
<vlv:VirtualListView.ItemTemplate>
<DataTemplate>
<Border
Margin="10,0,0,0"
Padding="4"
Background="LightBlue"
StrokeShape="{RoundRectangle CornerRadius=10}">
<Label Margin="10,6,10,6" Text="{Binding .}" />
</Border>
<DataTemplate x:DataType="local:Item">
<vlv:VirtualViewCell x:Name="cell">
<Border
Margin="10,0,0,0"
Padding="4"
Background="LightBlue"
StrokeShape="{RoundRectangle CornerRadius=10}">
<VerticalStackLayout>
<Button Text="Test" Clicked="ButtonAddTextClicked" CommandParameter="{DynamicResource ItemPosition}" />
<Label Margin="10,6,10,6" Text="{Binding Name}" />
</VerticalStackLayout>
</Border>
</vlv:VirtualViewCell>
</DataTemplate>
</vlv:VirtualListView.ItemTemplate>
</vlv:VirtualListView>
Expand Down
12 changes: 12 additions & 0 deletions Sample/VirtualListViewSample/SectionedAdapterPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace VirtualListViewSample;
Expand Down Expand Up @@ -53,4 +54,15 @@ private async void Vlv_OnOnRefresh(object sender, RefreshEventArgs e)
await Task.Delay(3000);
e.Complete();
}

private void ButtonAddTextClicked(object sender, EventArgs e)
{
if (sender is Button button)
{
if (button.CommandParameter is ItemPosition itemPosition)
{
this.Adapter.UpdateItem(itemPosition.SectionIndex, itemPosition.ItemIndex);
}
}
}
}
4 changes: 4 additions & 0 deletions VirtualListView/Adapters/IVirtualListViewAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ public interface IVirtualListViewAdapter
event EventHandler OnDataInvalidated;

void InvalidateData();

event EventHandler<InvalidateItemsEventArgs> OnItemsInvalidated;

void InvalidateItems(params ItemPosition[] items);
}
11 changes: 11 additions & 0 deletions VirtualListView/Adapters/InvalidateItemsEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Microsoft.Maui.Adapters;

public class InvalidateItemsEventArgs : EventArgs
{
public InvalidateItemsEventArgs(params ItemPosition[] items)
{
Items = items;
}

public ItemPosition[] Items { get; }
}
10 changes: 10 additions & 0 deletions VirtualListView/Adapters/VirtualListViewAdapterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public virtual int GetNumberOfSections() =>

public event EventHandler OnDataInvalidated;

public event EventHandler<InvalidateItemsEventArgs> OnItemsInvalidated;

public virtual void InvalidateData()
{
OnDataInvalidated?.Invoke(this, EventArgs.Empty);
Expand All @@ -31,4 +33,12 @@ object IVirtualListViewAdapter.GetSection(int sectionIndex)

void IVirtualListViewAdapter.InvalidateData()
=> InvalidateData();

public virtual void InvalidateItems(params ItemPosition[] items)
{
OnItemsInvalidated?.Invoke(this, new InvalidateItemsEventArgs(items));
}

void IVirtualListViewAdapter.InvalidateItems(params Microsoft.Maui.ItemPosition[] items)
=> InvalidateItems(items);
}
20 changes: 20 additions & 0 deletions VirtualListView/Apple/VirtualListViewHandler.ios.maccatalyst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,24 @@ public void InvalidateData()
});

}

void InvalidateItems(params ItemPosition[] items)
{
if (items is not null && items.Length > 0)
{
var paths = new List<NSIndexPath>();
foreach (var item in items)
{
paths.Add(NSIndexPath.FromItemSection(item.ItemIndex, item.SectionIndex));
}

if (paths.Count > 0)
{
this.PlatformView.InvokeOnMainThread(() =>
{
PlatformView.ReloadItems(paths.ToArray());
});
}
}
}
}
2 changes: 2 additions & 0 deletions VirtualListView/Controls/VirtualViewCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public int SectionIndex
{
sectionIndex = value;
this.Resources[nameof(SectionIndex)] = sectionIndex;
this.Resources[nameof(ItemPosition)] = new ItemPosition(sectionIndex, ItemIndex);
this.OnPropertyChanged(nameof(SectionIndex));
}
}
Expand All @@ -73,6 +74,7 @@ public int ItemIndex
{
itemIndex = value;
this.Resources[nameof(ItemIndex)] = itemIndex;
this.Resources[nameof(ItemPosition)] = new ItemPosition(SectionIndex, itemIndex);
this.OnPropertyChanged(nameof(ItemIndex));
this.OnPropertyChanged(nameof(IsFirstItemInSection));
this.OnPropertyChanged(nameof(IsNotFirstItemInSection));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,17 @@ void UpdateEmptyView()
UpdateEmptyViewVisibility();
}
}

void InvalidateItems(params ItemPosition[] items)
{
if (items is not null && items.Length > 0)
{
foreach (var item in items)
{
var rawPosition = PositionalViewSelector.GetPosition(item.SectionIndex, item.ItemIndex);

adapter.NotifyItemChanged(rawPosition);
}
}
}
}
7 changes: 7 additions & 0 deletions VirtualListView/Platforms/Windows/IrSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;

namespace Microsoft.Maui;

Expand All @@ -26,6 +27,12 @@ public void Reset()
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

public void ResetItems(params ItemPosition[] items)
{
// TODO: Fire a more specific event
Reset();
}

public int Count
=> PositionalViewSelector?.TotalCount ?? 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,10 @@ void UpdateEmptyView()

UpdateEmptyViewVisibility();
}

void InvalidateItems(params ItemPosition[] items)
{
if (items is not null && items.Length > 0)
irSource?.ResetItems(items);
}
}
13 changes: 12 additions & 1 deletion VirtualListView/VirtualListViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public partial class VirtualListViewHandler

public static CommandMapper<IVirtualListView, VirtualListViewHandler> CommandMapper = new(ViewCommandMapper)
{
[nameof(IVirtualListView.ScrollToItem)] = MapScrollToItem,
[nameof(IVirtualListView.ScrollToItem)] = MapScrollToItem
};

public static void MapScrollToItem(VirtualListViewHandler handler, IVirtualListView view, object parameter)
Expand Down Expand Up @@ -67,10 +67,16 @@ bool ShouldShowEmptyView
public static void MapAdapter(VirtualListViewHandler handler, IVirtualListView virtualListView)
{
if (handler.currentAdapter != null)
{
handler.currentAdapter.OnDataInvalidated -= handler.Adapter_OnDataInvalidated;
handler.currentAdapter.OnItemsInvalidated -= handler.Adapter_OnItemsInvalidated;
}

if (virtualListView?.Adapter != null)
{
virtualListView.Adapter.OnDataInvalidated += handler.Adapter_OnDataInvalidated;
virtualListView.Adapter.OnItemsInvalidated += handler.Adapter_OnItemsInvalidated;
}

handler.currentAdapter = virtualListView.Adapter;
handler?.InvalidateData();
Expand All @@ -83,6 +89,11 @@ void Adapter_OnDataInvalidated(object sender, EventArgs e)
InvalidateData();
}

void Adapter_OnItemsInvalidated(object sender, InvalidateItemsEventArgs e)
{
InvalidateItems(e.Items);
}

public bool IsItemSelected(int sectionIndex, int itemIndex)
{
if (VirtualView is null)
Expand Down

0 comments on commit df31f04

Please sign in to comment.