Skip to content

Commit a1bfddd

Browse files
niels9001Copilot
andcommitted
Add ConnectedAnimation sample with ItemsRepeater (#340)
Add a new sample demonstrating how to use ConnectedAnimation with ItemsRepeater, which requires a different approach than ListView/GridView. Key differences from ListView/GridView approach: - ItemsRepeater lacks PrepareConnectedAnimation() and TryStartConnectedAnimationAsync() convenience methods - Must use ConnectedAnimationService.PrepareToAnimate() directly - Must manually find the animated element via visual tree walking - Must manually save/restore scroll position for back navigation New files: - ItemsRepeaterCollectionPage.xaml/.cs: Grid of items using ItemsRepeater with UniformGridLayout. Clicking an item navigates to the existing DetailedInfoPage with a connected animation. Back navigation restores scroll position and plays a back animation. - ConnectedAnimationSample4_xaml.txt / _cs.txt: Sample code snippets Modified files: - ConnectedAnimationPage.xaml: Add 4th sample section with Frame - ConnectedAnimationPage.xaml.cs: Navigate to new page on load Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9ba97da commit a1bfddd

File tree

10 files changed

+348
-86
lines changed

10 files changed

+348
-86
lines changed

WinUIGallery/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"WinUIGallery Packaged": {
44
"commandName": "MsixPackage",
5-
"nativeDebugging": true
5+
"nativeDebugging": false
66
},
77
"WinUIGallery Unpackaged": {
88
"commandName": "Project",

WinUIGallery/Samples/ControlPages/ConnectedAnimationPage.xaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,22 @@
5656
MinWidth="500"
5757
MinHeight="300" />
5858
</controls:ControlExample>
59+
60+
<controls:ControlExample
61+
CSharpSource="Motion/ConnectedAnimation/ConnectedAnimationSample4_cs.txt"
62+
HeaderText="Connected animation with ItemsRepeater"
63+
XamlSource="Motion/ConnectedAnimation/ConnectedAnimationSample4_xaml.txt">
64+
<StackPanel>
65+
<TextBlock Margin="0,0,0,12" TextWrapping="WrapWholeWords">
66+
Unlike ListView and GridView, ItemsRepeater does not have built-in ConnectedAnimation methods.
67+
Use ConnectedAnimationService.PrepareToAnimate() directly, and manually find the target element in the visual tree.
68+
Click an item to navigate with a connected animation.
69+
</TextBlock>
70+
<Frame
71+
x:Name="ItemsRepeaterFrame"
72+
Height="400"
73+
MinWidth="500" />
74+
</StackPanel>
75+
</controls:ControlExample>
5976
</StackPanel>
6077
</Page>

WinUIGallery/Samples/ControlPages/ConnectedAnimationPage.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public ConnectedAnimationPage()
2424

2525
// For 3rd sample
2626
ContentFrame.Navigate(typeof(SamplePage1));
27+
28+
// For 4th sample (ItemsRepeater)
29+
ItemsRepeaterFrame.Navigate(typeof(ItemsRepeaterCollectionPage));
2730
}
2831

2932
private ConnectedAnimationConfiguration? GetConfiguration()
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// ItemsRepeater does not have PrepareConnectedAnimation() or
2+
// TryStartConnectedAnimationAsync() like ListView/GridView.
3+
// Use ConnectedAnimationService.PrepareToAnimate() directly instead.
4+
5+
private CustomDataObject _storedItem;
6+
private double _persistedScrollPosition;
7+
8+
private void Repeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs args)
9+
{
10+
// Attach a Tapped handler to each item container.
11+
args.Element.Tapped -= Item_Tapped;
12+
args.Element.Tapped += Item_Tapped;
13+
}
14+
15+
private void Item_Tapped(object sender, TappedRoutedEventArgs e)
16+
{
17+
var element = sender as FrameworkElement;
18+
_storedItem = repeater.ItemsSourceView.GetAt(
19+
repeater.GetElementIndex(element)) as CustomDataObject;
20+
21+
// Find the named element in the DataTemplate and prepare the animation.
22+
if (FindChildByName(element, "connectedElement") is UIElement source)
23+
{
24+
ConnectedAnimationService.GetForCurrentView()
25+
.PrepareToAnimate("ForwardConnectedAnimation", source);
26+
}
27+
28+
// Save scroll position for back navigation.
29+
_persistedScrollPosition = scrollViewer.VerticalOffset;
30+
31+
Frame.Navigate(typeof(DetailPage), _storedItem,
32+
new SuppressNavigationTransitionInfo());
33+
}
34+
35+
protected override void OnNavigatedTo(NavigationEventArgs e)
36+
{
37+
base.OnNavigatedTo(e);
38+
if (_storedItem == null) return;
39+
40+
// Restore scroll position so the target element is visible.
41+
scrollViewer.ChangeView(null, _persistedScrollPosition, null, true);
42+
UpdateLayout();
43+
44+
var animation = ConnectedAnimationService.GetForCurrentView()
45+
.GetAnimation("BackConnectedAnimation");
46+
if (animation != null)
47+
{
48+
animation.Configuration = new DirectConnectedAnimationConfiguration();
49+
50+
int index = repeater.ItemsSourceView.IndexOf(_storedItem);
51+
if (repeater.TryGetElement(index) is FrameworkElement container
52+
&& FindChildByName(container, "connectedElement") is UIElement target)
53+
{
54+
animation.TryStart(target);
55+
}
56+
}
57+
}
58+
59+
// Helper to find a named element within a DataTemplate.
60+
private static UIElement FindChildByName(DependencyObject parent, string name)
61+
{
62+
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
63+
{
64+
var child = VisualTreeHelper.GetChild(parent, i);
65+
if (child is FrameworkElement fe && fe.Name == name)
66+
return fe;
67+
var result = FindChildByName(child, name);
68+
if (result != null)
69+
return result;
70+
}
71+
return null;
72+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!-- Unlike ListView/GridView, ItemsRepeater does not have built-in
2+
ConnectedAnimation methods. Use ConnectedAnimationService directly. -->
3+
4+
<ScrollViewer x:Name="scrollViewer">
5+
<ItemsRepeater
6+
x:Name="repeater"
7+
ItemsSource="{x:Bind Items}">
8+
<ItemsRepeater.Layout>
9+
<UniformGridLayout
10+
MinColumnSpacing="8"
11+
MinItemHeight="120"
12+
MinItemWidth="150"
13+
MinRowSpacing="8" />
14+
</ItemsRepeater.Layout>
15+
<ItemsRepeater.ItemTemplate>
16+
<DataTemplate x:DataType="local:CustomDataObject">
17+
<Grid CornerRadius="4">
18+
<!-- The element named "connectedElement" will be animated -->
19+
<Image x:Name="connectedElement"
20+
Source="{x:Bind ImageLocation}"
21+
Stretch="UniformToFill" />
22+
<Border VerticalAlignment="Bottom"
23+
Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}"
24+
Padding="8,4">
25+
<TextBlock Text="{x:Bind Title}"
26+
Style="{ThemeResource CaptionTextBlockStyle}" />
27+
</Border>
28+
</Grid>
29+
</DataTemplate>
30+
</ItemsRepeater.ItemTemplate>
31+
</ItemsRepeater>
32+
</ScrollViewer>

WinUIGallery/Samples/SamplePages/CardPage.xaml

Lines changed: 50 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,29 @@
1616
<GridView.ItemContainerStyle>
1717
<Style BasedOn="{StaticResource GridViewItemRevealStyle}" TargetType="GridViewItem">
1818
<Style.Setters>
19-
<Setter Property="Margin" Value="12" />
19+
<Setter Property="Margin" Value="4" />
2020
</Style.Setters>
2121
</Style>
2222
</GridView.ItemContainerStyle>
2323
<GridView.ItemTemplate>
2424
<DataTemplate>
2525
<Grid
2626
x:Name="connectedElement"
27-
Width="190"
28-
Height="250"
29-
AutomationProperties.Name="{Binding}">
30-
<Grid.RowDefinitions>
31-
<RowDefinition Height="Auto" />
32-
<RowDefinition Height="*" />
33-
</Grid.RowDefinitions>
34-
<Grid
35-
Height="100"
36-
HorizontalAlignment="Stretch"
37-
VerticalAlignment="Stretch"
38-
Background="{ThemeResource SystemAccentColor}">
27+
Width="150"
28+
Height="110"
29+
CornerRadius="4"
30+
AutomationProperties.Name="{Binding Title}">
31+
<Image
32+
Source="{Binding ImageLocation}"
33+
Stretch="UniformToFill" />
34+
<Border
35+
VerticalAlignment="Bottom"
36+
Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}"
37+
Padding="8,4">
3938
<TextBlock
40-
HorizontalAlignment="Center"
41-
VerticalAlignment="Center"
42-
Style="{ThemeResource TitleTextBlockStyle}"
43-
Text="Item" />
44-
</Grid>
45-
<Grid
46-
Grid.Row="1"
47-
HorizontalAlignment="Stretch"
48-
VerticalAlignment="Stretch"
49-
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}">
50-
<TextBlock
51-
Margin="12"
52-
HorizontalAlignment="Center"
53-
VerticalAlignment="Center"
54-
Text="{Binding}" />
55-
</Grid>
39+
Style="{ThemeResource CaptionTextBlockStyle}"
40+
Text="{Binding Title}" />
41+
</Border>
5642
</Grid>
5743
</DataTemplate>
5844
</GridView.ItemTemplate>
@@ -68,50 +54,48 @@
6854
</Grid.Background>
6955
<Grid
7056
x:Name="destinationElement"
71-
Width="320"
72-
Height="400"
57+
Width="400"
58+
Height="320"
7359
HorizontalAlignment="Center"
7460
VerticalAlignment="Center"
75-
BorderBrush="{ThemeResource SystemAccentColor}"
76-
BorderThickness="1">
61+
CornerRadius="8">
7762
<Grid.RowDefinitions>
78-
<RowDefinition Height="Auto" />
7963
<RowDefinition Height="*" />
64+
<RowDefinition Height="Auto" />
8065
</Grid.RowDefinitions>
81-
<Grid
82-
Height="170"
83-
HorizontalAlignment="Stretch"
84-
VerticalAlignment="Stretch"
85-
Background="{ThemeResource SystemAccentColor}">
86-
<TextBlock
87-
Margin="12"
88-
VerticalAlignment="Center"
89-
Style="{ThemeResource HeaderTextBlockStyle}"
90-
Text="Header" />
91-
<Button
92-
Width="40"
93-
Height="40"
94-
Margin="5"
95-
HorizontalAlignment="Right"
96-
VerticalAlignment="Top"
97-
AutomationProperties.Name="Close"
98-
Click="BackButton_Click"
99-
ToolTipService.ToolTip="Close">
100-
<Button.Content>
101-
<SymbolIcon Symbol="Clear" />
102-
</Button.Content>
103-
</Button>
104-
</Grid>
105-
<Grid
66+
<Image
67+
x:Name="detailImage"
68+
Grid.Row="0"
69+
Source="{Binding ImageLocation}"
70+
Stretch="UniformToFill" />
71+
<Button
72+
Width="32"
73+
Height="32"
74+
Margin="8"
75+
HorizontalAlignment="Right"
76+
VerticalAlignment="Top"
77+
AutomationProperties.Name="Close"
78+
Click="BackButton_Click"
79+
ToolTipService.ToolTip="Close">
80+
<Button.Content>
81+
<SymbolIcon Symbol="Clear" />
82+
</Button.Content>
83+
</Button>
84+
<StackPanel
10685
Grid.Row="1"
107-
HorizontalAlignment="Stretch"
108-
VerticalAlignment="Stretch"
109-
Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}">
86+
Padding="16,12"
87+
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
88+
<TextBlock
89+
x:Name="detailTitle"
90+
Style="{ThemeResource SubtitleTextBlockStyle}" />
11091
<TextBlock
111-
Margin="12"
112-
Style="{ThemeResource BaseTextBlockStyle}"
113-
Text="Content" />
114-
</Grid>
92+
x:Name="detailDescription"
93+
Margin="0,4,0,0"
94+
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
95+
Style="{ThemeResource BodyTextBlockStyle}"
96+
TextWrapping="Wrap"
97+
MaxLines="3" />
98+
</StackPanel>
11599
</Grid>
116100
</Grid>
117101

WinUIGallery/Samples/SamplePages/CardPage.xaml.cs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,19 @@
55
using Microsoft.UI.Xaml.Controls;
66
using Microsoft.UI.Xaml.Media.Animation;
77
using System;
8-
using System.Collections.Generic;
98
using Windows.Foundation.Metadata;
9+
using WinUIGallery.ControlPages;
1010

1111
namespace WinUIGallery.SamplePages;
1212

1313
public sealed partial class CardPage : Page
1414
{
15-
int _storedItem;
15+
CustomDataObject? _storedItem;
1616

1717
public CardPage()
1818
{
1919
this.InitializeComponent();
20-
21-
// Populate the collection with some items.
22-
var items = new List<int>();
23-
for (int i = 0; i < 30; i++)
24-
{
25-
items.Add(i);
26-
}
27-
28-
collection.ItemsSource = items;
20+
collection.ItemsSource = CustomDataObject.GetDataObjects(includeAllItems: true);
2921
}
3022

3123
private async void BackButton_Click(object sender, RoutedEventArgs e)
@@ -40,13 +32,13 @@ private async void BackButton_Click(object sender, RoutedEventArgs e)
4032
collection.ScrollIntoView(_storedItem, ScrollIntoViewAlignment.Default);
4133
collection.UpdateLayout();
4234

43-
// Use the Direct configuration to go back (if the API is available).
35+
// Use the Direct configuration to go back (if the API is available).
4436
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7))
4537
{
4638
animation.Configuration = new DirectConnectedAnimationConfiguration();
4739
}
4840

49-
// Play the second connected animation.
41+
// Play the second connected animation.
5042
await collection.TryStartConnectedAnimationAsync(animation, _storedItem, "connectedElement");
5143
}
5244

@@ -60,17 +52,19 @@ private void TipsGrid_ItemClick(object sender, ItemClickEventArgs e)
6052
{
6153
ConnectedAnimation? animation = null;
6254

63-
// Get the collection item corresponding to the clicked item.
6455
if (collection.ContainerFromItem(e.ClickedItem) is GridViewItem container)
6556
{
66-
// Stash the clicked item for use later. We'll need it when we connect back from the detailpage.
67-
_storedItem = Convert.ToInt32(container.Content);
57+
_storedItem = container.Content as CustomDataObject;
6858

69-
// Prepare the connected animation.
70-
// Notice that the stored item is passed in, as well as the name of the connected element.
71-
// The animation will actually start on the Detailed info page.
7259
animation = collection.PrepareConnectedAnimation("forwardAnimation", _storedItem, "connectedElement");
60+
}
7361

62+
// Update the detail view with the clicked item's data.
63+
if (_storedItem != null)
64+
{
65+
detailImage.Source = new Microsoft.UI.Xaml.Media.Imaging.BitmapImage(new System.Uri("ms-appx://" + _storedItem.ImageLocation));
66+
detailTitle.Text = _storedItem.Title;
67+
detailDescription.Text = _storedItem.Description;
7468
}
7569

7670
SmokeGrid.Visibility = Visibility.Visible;

0 commit comments

Comments
 (0)