Skip to content

Commit c3f42a9

Browse files
authored
[Windows] Implement ItemsUpdatingScrollMode on CollectionView (#15601)
* Implement ItemsUpdatingScrollMode on CollectionView Windows * Unsubscribe before a subscription * Fixed wrong name
1 parent 3417967 commit c3f42a9

6 files changed

Lines changed: 187 additions & 7 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Reflection;
3+
using Microsoft.Maui.Controls;
4+
5+
namespace Maui.Controls.Sample.Pages.CollectionViewGalleries.ScrollModeGalleries
6+
{
7+
class EnumPicker : Picker
8+
{
9+
public static readonly BindableProperty EnumTypeProperty =
10+
BindableProperty.Create(nameof(EnumType), typeof(Type), typeof(EnumPicker),
11+
propertyChanged: (bindable, oldValue, newValue) =>
12+
{
13+
EnumPicker picker = (EnumPicker)bindable;
14+
15+
if (oldValue != null)
16+
{
17+
picker.ItemsSource = null;
18+
}
19+
if (newValue != null)
20+
{
21+
if (!((Type)newValue).GetTypeInfo().IsEnum)
22+
throw new ArgumentException("EnumPicker: EnumType property must be enumeration type");
23+
24+
picker.ItemsSource = Enum.GetValues((Type)newValue);
25+
}
26+
});
27+
28+
public Type EnumType
29+
{
30+
set => SetValue(EnumTypeProperty, value);
31+
get => (Type)GetValue(EnumTypeProperty);
32+
}
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage
3+
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5+
x:Class="Maui.Controls.Sample.Pages.CollectionViewGalleries.ScrollModeGalleries.ItemsUpdatingScrollModeGallery"
6+
xmlns:controls="clr-namespace:Maui.Controls.Sample.Pages.CollectionViewGalleries.ScrollModeGalleries"
7+
Title="ItemsUpdatingScrollMode Gallery">
8+
<Grid
9+
RowDefinitions="Auto, *" Margin="20">
10+
<StackLayout
11+
Orientation="Horizontal"
12+
HorizontalOptions="Center">
13+
<Label
14+
Text="UpdatingScrollMode: "
15+
VerticalTextAlignment="Center" />
16+
<controls:EnumPicker
17+
x:Name="enumPicker"
18+
EnumType="{x:Type ItemsUpdatingScrollMode}"
19+
SelectedIndex="0"
20+
SelectedIndexChanged="OnItemsUpdatingScrollModeChanged" />
21+
</StackLayout>
22+
<CollectionView
23+
x:Name="CollectionView"
24+
Grid.Row="1"
25+
ItemsSource="{Binding Items}">
26+
<CollectionView.ItemTemplate>
27+
<DataTemplate>
28+
<Grid
29+
Padding="12">
30+
<Grid.RowDefinitions>
31+
<RowDefinition Height="Auto" />
32+
<RowDefinition Height="Auto" />
33+
</Grid.RowDefinitions>
34+
<Label
35+
Text="{Binding Text1}"
36+
FontAttributes="Bold" />
37+
<Label
38+
Grid.Row="1"
39+
Text="{Binding Text2}"
40+
FontAttributes="Italic"
41+
VerticalOptions="End" />
42+
</Grid>
43+
</DataTemplate>
44+
</CollectionView.ItemTemplate>
45+
</CollectionView>
46+
</Grid>
47+
</ContentPage>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.Collections.ObjectModel;
3+
using System.Threading.Tasks;
4+
using Microsoft.Maui;
5+
using Microsoft.Maui.Controls;
6+
7+
namespace Maui.Controls.Sample.Pages.CollectionViewGalleries.ScrollModeGalleries
8+
{
9+
public class ItemsUpdatingScrollModeItem
10+
{
11+
public string Text1 { get; set; }
12+
public string Text2 { get; set; }
13+
}
14+
15+
public class ItemsUpdatingScrollModeViewModel : BindableObject
16+
{
17+
public ObservableCollection<ItemsUpdatingScrollModeItem> Items { get; private set; } = new ObservableCollection<ItemsUpdatingScrollModeItem>();
18+
19+
public async Task LoadItemsAsync()
20+
{
21+
for (int i = 0; i < 50; i++)
22+
{
23+
Items.Add(new ItemsUpdatingScrollModeItem
24+
{
25+
Text1 = $"Title {i + 1}",
26+
Text2 = $"Subtitle {i + 1}",
27+
});
28+
29+
await Task.Delay(1000);
30+
}
31+
}
32+
}
33+
34+
public partial class ItemsUpdatingScrollModeGallery : ContentPage
35+
{
36+
ItemsUpdatingScrollModeViewModel _viewModel;
37+
public ItemsUpdatingScrollModeGallery()
38+
{
39+
InitializeComponent();
40+
41+
BindingContext = _viewModel = new ItemsUpdatingScrollModeViewModel();
42+
}
43+
44+
protected override async void OnAppearing()
45+
{
46+
base.OnAppearing();
47+
48+
await _viewModel.LoadItemsAsync();
49+
}
50+
51+
void OnItemsUpdatingScrollModeChanged(object sender, EventArgs e)
52+
{
53+
CollectionView.ItemsUpdatingScrollMode = (ItemsUpdatingScrollMode)(sender as EnumPicker).SelectedItem;
54+
}
55+
}
56+
}

src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/ScrollModeGalleries/ScrollModeGallery.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ public ScrollModeGallery()
2323
{
2424
descriptionLabel,
2525
GalleryBuilder.NavButton("Scroll Modes Testing", () =>
26-
new ScrollModeTestGallery(), Navigation)
26+
new ScrollModeTestGallery(), Navigation),
27+
GalleryBuilder.NavButton("ItemsUpdatingScrollMode Gallery", () =>
28+
new ItemsUpdatingScrollModeGallery(), Navigation)
2729
}
2830
}
2931
};
3032
}
3133
}
32-
}
34+
}

src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/ScrollModeGalleries/ScrollModeTestGallery.xaml.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
72
using Microsoft.Maui.Controls;
83
using Microsoft.Maui.Controls.Xaml;
94

src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,53 @@ public static void MapIsVisible(ItemsViewHandler<TItemsView> handler, ItemsView
106106

107107
public static void MapItemsUpdatingScrollMode(ItemsViewHandler<TItemsView> handler, ItemsView itemsView)
108108
{
109+
handler.UpdateItemsUpdatingScrollMode();
110+
}
111+
112+
void UpdateItemsUpdatingScrollMode()
113+
{
114+
if (PlatformView is null || PlatformView.Items is null)
115+
return;
116+
117+
if (VirtualView.ItemsUpdatingScrollMode == ItemsUpdatingScrollMode.KeepScrollOffset)
118+
{
119+
// The scroll position is maintained when new items are added as the default,
120+
// so we don't need to watch for data changes
121+
PlatformView.Items.VectorChanged -= OnItemsVectorChanged;
122+
}
123+
else
124+
{
125+
PlatformView.Items.VectorChanged -= OnItemsVectorChanged;
126+
PlatformView.Items.VectorChanged += OnItemsVectorChanged;
127+
}
128+
}
129+
130+
void OnItemsVectorChanged(global::Windows.Foundation.Collections.IObservableVector<object> sender, global::Windows.Foundation.Collections.IVectorChangedEventArgs @event)
131+
{
132+
if (VirtualView is null)
133+
return;
134+
135+
if (sender is not ItemCollection items)
136+
return;
137+
138+
var itemsCount = items.Count;
139+
140+
if (itemsCount == 0)
141+
return;
142+
143+
if (VirtualView.ItemsUpdatingScrollMode == ItemsUpdatingScrollMode.KeepItemsInView)
144+
{
145+
var firstItem = items[0];
146+
// Keeps the first item in the list displayed when new items are added.
147+
ListViewBase.ScrollIntoView(firstItem);
148+
}
109149

150+
if (VirtualView.ItemsUpdatingScrollMode == ItemsUpdatingScrollMode.KeepLastItemInView)
151+
{
152+
var lastItem = items[itemsCount - 1];
153+
// Adjusts the scroll offset to keep the last item in the list displayed when new items are added.
154+
ListViewBase.ScrollIntoView(lastItem);
155+
}
110156
}
111157

112158
protected abstract ListViewBase SelectListViewBase();

0 commit comments

Comments
 (0)