Skip to content

Commit 9ed4cef

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 9ed4cef

13 files changed

Lines changed: 399 additions & 154 deletions

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: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,17 @@
1-
// To see the source code: https://github.com/microsoft/WinUI-Gallery/blob/main/WinUIGallery/ConnectedAnimationPages/CollectionPage.xaml.cs
2-
3-
public sealed partial class CardPage : Page
1+
public sealed partial class CardPage : Page
42
{
5-
int _storedItem;
3+
CustomDataObject? _storedItem;
64

75
public CardPage()
86
{
97
this.InitializeComponent();
10-
11-
// Populate the collection with some items.
12-
var items = new List<int>();
13-
for (int i = 0; i < 30; i++)
14-
{
15-
items.Add(i);
16-
}
17-
18-
collection.ItemsSource = items;
8+
collection.ItemsSource = CustomDataObject.GetDataObjects(includeAllItems: true);
199
}
2010

2111
private async void BackButton_Click(object sender, RoutedEventArgs e)
2212
{
23-
ConnectedAnimation animation = ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("backwardsAnimation", destinationElement);
13+
ConnectedAnimation animation = ConnectedAnimationService.GetForCurrentView()
14+
.PrepareToAnimate("backwardsAnimation", destinationElement);
2415
SmokeGrid.Children.Remove(destinationElement);
2516

2617
// Collapse the smoke when the animation completes.
@@ -30,13 +21,9 @@ public sealed partial class CardPage : Page
3021
collection.ScrollIntoView(_storedItem, ScrollIntoViewAlignment.Default);
3122
collection.UpdateLayout();
3223

33-
// Use the Direct configuration to go back (if the API is available).
34-
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7))
35-
{
36-
animation.Configuration = new DirectConnectedAnimationConfiguration();
37-
}
24+
animation.Configuration = new DirectConnectedAnimationConfiguration();
3825

39-
// Play the second connected animation.
26+
// Play the connected animation back to the collection.
4027
await collection.TryStartConnectedAnimationAsync(animation, _storedItem, "connectedElement");
4128
}
4229

@@ -48,23 +35,23 @@ public sealed partial class CardPage : Page
4835

4936
private void TipsGrid_ItemClick(object sender, ItemClickEventArgs e)
5037
{
51-
ConnectedAnimation animation = null;
38+
ConnectedAnimation? animation = null;
5239

53-
// Get the collection item corresponding to the clicked item.
5440
if (collection.ContainerFromItem(e.ClickedItem) is GridViewItem container)
5541
{
56-
// Stash the clicked item for use later. We'll need it when we connect back from the detailpage.
57-
_storedItem = Convert.ToInt32(container.Content);
58-
59-
// Prepare the connected animation.
60-
// Notice that the stored item is passed in, as well as the name of the connected element.
61-
// The animation will actually start on the Detailed info page.
42+
_storedItem = container.Content as CustomDataObject;
6243
animation = collection.PrepareConnectedAnimation("forwardAnimation", _storedItem, "connectedElement");
44+
}
6345

46+
// Update the detail view with the clicked item's data.
47+
if (_storedItem != null)
48+
{
49+
detailImage.Source = new BitmapImage(new Uri("ms-appx://" + _storedItem.ImageLocation));
50+
detailTitle.Text = _storedItem.Title;
51+
detailDescription.Text = _storedItem.Description;
6452
}
6553

6654
SmokeGrid.Visibility = Visibility.Visible;
67-
68-
animation.TryStart(destinationElement);
55+
animation?.TryStart(destinationElement);
6956
}
7057
}
Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,52 @@
1-
<GridView x:Name="collection" IsItemClickEnabled="True" ItemClick="TipsGrid_ItemClick" HorizontalAlignment="Center" MaxWidth="1400">
1+
<GridView x:Name="collection" IsItemClickEnabled="True" ItemClick="TipsGrid_ItemClick"
2+
HorizontalAlignment="Center" MaxWidth="1400">
23
<GridView.ItemContainerStyle>
34
<Style BasedOn="{StaticResource GridViewItemRevealStyle}" TargetType="GridViewItem">
45
<Style.Setters>
5-
<Setter Property="Margin" Value="12" />
6+
<Setter Property="Margin" Value="4" />
67
</Style.Setters>
78
</Style>
89
</GridView.ItemContainerStyle>
910
<GridView.ItemTemplate>
1011
<DataTemplate>
11-
<Grid x:Name="connectedElement" Height="250" Width="190" AutomationProperties.Name="{Binding}">
12-
<Grid.RowDefinitions>
13-
<RowDefinition Height="Auto" />
14-
<RowDefinition Height="*" />
15-
</Grid.RowDefinitions>
16-
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}" Height="100">
17-
<TextBlock Text="Item" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{ThemeResource TitleTextBlockStyle}" />
18-
</Grid>
19-
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" Grid.Row="1">
20-
<TextBlock Text="{Binding}" Margin="12" HorizontalAlignment="Center" VerticalAlignment="Center"/>
21-
</Grid>
12+
<Grid x:Name="connectedElement" Width="150" Height="110"
13+
AutomationProperties.Name="{Binding Title}" CornerRadius="4">
14+
<Image Source="{Binding ImageLocation}" Stretch="UniformToFill" />
15+
<Border Padding="8,4" VerticalAlignment="Bottom"
16+
Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}">
17+
<TextBlock Style="{ThemeResource CaptionTextBlockStyle}" Text="{Binding Title}" />
18+
</Border>
2219
</Grid>
2320
</DataTemplate>
2421
</GridView.ItemTemplate>
2522
</GridView>
2623

27-
<Grid x:Name="SmokeGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="Collapsed" >
28-
<Grid.Background>
29-
<SolidColorBrush Color="{ThemeResource SystemChromeAltHighColor}" Opacity="0.8" />
30-
</Grid.Background>
31-
<Grid x:Name="destinationElement" HorizontalAlignment="Center" VerticalAlignment="Center" Width="320" Height="400" BorderThickness="1" BorderBrush="{ThemeResource SystemAccentColor}">
24+
<Grid x:Name="SmokeGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
25+
Background="{ThemeResource SmokeFillColorDefaultBrush}" Visibility="Collapsed">
26+
<Grid x:Name="destinationElement" Width="400" Height="320"
27+
HorizontalAlignment="Center" VerticalAlignment="Center"
28+
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}" BorderThickness="1"
29+
CornerRadius="8">
3230
<Grid.RowDefinitions>
33-
<RowDefinition Height="Auto" />
3431
<RowDefinition Height="*" />
32+
<RowDefinition Height="Auto" />
3533
</Grid.RowDefinitions>
36-
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}" Height="170">
37-
<TextBlock Text="Header" Style="{ThemeResource HeaderTextBlockStyle}" Margin="12" VerticalAlignment="Center" />
38-
<Button Click="BackButton_Click" HorizontalAlignment="Right" VerticalAlignment="Top" Height="40" Width="40" Margin="5"
39-
ToolTipService.ToolTip="Close" AutomationProperties.Name="Close">
40-
<Button.Content>
41-
<SymbolIcon Symbol="Clear" />
42-
</Button.Content>
43-
</Button>
44-
</Grid>
45-
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" Grid.Row="1">
46-
<TextBlock Text="Content" Style="{ThemeResource BaseTextBlockStyle}" Margin="12" />
47-
</Grid>
34+
<Image x:Name="detailImage" Grid.Row="0" Stretch="UniformToFill" />
35+
<Button Width="36" Height="36" Margin="8"
36+
HorizontalAlignment="Right" VerticalAlignment="Top"
37+
AutomationProperties.Name="Close" Click="BackButton_Click"
38+
ToolTipService.ToolTip="Close">
39+
<Button.Content>
40+
<FontIcon FontSize="14" Glyph="&#xE711;" />
41+
</Button.Content>
42+
</Button>
43+
<StackPanel Grid.Row="1" Padding="16,12"
44+
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
45+
<TextBlock x:Name="detailTitle" Style="{ThemeResource SubtitleTextBlockStyle}" />
46+
<TextBlock x:Name="detailDescription" Margin="0,4,0,0"
47+
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
48+
MaxLines="3" Style="{ThemeResource BodyTextBlockStyle}"
49+
TextWrapping="Wrap" />
50+
</StackPanel>
4851
</Grid>
4952
</Grid>
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>

0 commit comments

Comments
 (0)