Skip to content

Commit 5622837

Browse files
committed
Aot-safe TextMemberPath access
1 parent dde65e5 commit 5622837

File tree

7 files changed

+68
-25
lines changed

7 files changed

+68
-25
lines changed

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.cs

+22-20
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,33 @@ protected override void OnApplyTemplate()
5555

5656
public void OnItemClicked()
5757
{
58-
if (_ownerRef is not null &&
59-
_ownerRef.TryGetTarget(out var breadcrumbBar))
58+
if (_ownerRef is null ||
59+
!_ownerRef.TryGetTarget(out var breadcrumbBar))
60+
return;
61+
62+
if (IsEllipsis)
6063
{
61-
if (IsEllipsis)
62-
{
63-
// Clear items in the ellipsis flyout
64-
_itemEllipsisDropDownMenuFlyout.Items.Clear();
64+
// Clear items in the ellipsis flyout
65+
_itemEllipsisDropDownMenuFlyout.Items.Clear();
6566

66-
// Populate items in the ellipsis flyout
67-
for (int index = 0; index < breadcrumbBar.IndexAfterEllipsis; index++)
67+
// Populate items in the ellipsis flyout
68+
for (int index = 0; index < breadcrumbBar.IndexAfterEllipsis; index++)
69+
{
70+
if (breadcrumbBar.TryGetElement(index, out var item) && item?.Content is string text)
6871
{
69-
if (breadcrumbBar.TryGetElement(index, out var item) && item?.Content is string text)
70-
{
71-
_itemEllipsisDropDownMenuFlyout.Items.Add(new MenuFlyoutItem() { Text = text });
72-
}
72+
var menuFlyoutItem = new MenuFlyoutItem() { Text = text };
73+
_itemEllipsisDropDownMenuFlyout.Items.Add(menuFlyoutItem);
74+
menuFlyoutItem.Click += (sender, e) => breadcrumbBar.RaiseItemClickedEvent(item);
7375
}
74-
75-
// Open the ellipsis flyout
76-
FlyoutBase.ShowAttachedFlyout(_itemContentButton);
77-
}
78-
else
79-
{
80-
// Fire a click event
81-
breadcrumbBar.RaiseItemClickedEvent(this);
8276
}
77+
78+
// Open the ellipsis flyout
79+
FlyoutBase.ShowAttachedFlyout(_itemContentButton);
80+
}
81+
else
82+
{
83+
// Fire a click event
84+
breadcrumbBar.RaiseItemClickedEvent(this);
8385
}
8486
}
8587

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Controls
5+
{
6+
/// <summary>
7+
/// An interface that provides a way to get the text member path of <see cref="OmnibarMode.SuggestionItemsSource"/>.
8+
/// </summary>
9+
/// <remarks>
10+
/// An alternative to this interface is to use an <see cref="Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation"/> powered by CsWinRT.
11+
/// </remarks>
12+
public interface IOmnibarTextMemberPathProvider
13+
{
14+
/// <summary>
15+
/// Retrieves the path of the text member as a string. This path can be used to identify the location of the text member.
16+
/// </summary>
17+
/// <returns>Returns a string representing the path of the text member.</returns>
18+
string GetTextMemberPath(string textMemberPath);
19+
}
20+
}

src/Files.App.Controls/Omnibar/Omnibar.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// Licensed under the MIT License.
33

44
using Microsoft.UI.Xaml.Controls;
5+
using Microsoft.UI.Xaml.Data;
56
using Microsoft.UI.Xaml.Markup;
67
using Microsoft.UI.Xaml.Media.Animation;
78
using Windows.Foundation;
9+
using WinRT;
810
using static System.Net.Mime.MediaTypeNames;
911

1012
namespace Files.App.Controls
@@ -227,9 +229,9 @@ private string GetObjectText(object obj)
227229
// Get the text to put into the text box from the chosen suggestion item
228230
return obj is string text
229231
? text
230-
: CurrentSelectedMode.DisplayMemberPath is null
231-
? obj.ToString() ?? string.Empty
232-
: obj.GetType().GetProperty(CurrentSelectedMode.DisplayMemberPath)?.GetValue(obj)?.ToString() ?? string.Empty;
232+
: obj is IOmnibarTextMemberPathProvider textMemberPathProvider
233+
? textMemberPathProvider.GetTextMemberPath(CurrentSelectedMode.DisplayMemberPath ?? string.Empty)
234+
: obj.ToString() ?? string.Empty;
233235
}
234236

235237
private void RevertTextToUserInput()
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4+
using Files.App.Controls;
5+
using System;
6+
47
namespace Files.App.UITests.Data
58
{
6-
internal record OmnibarPaletteSuggestionItem(string Title, string Description, string HotKeys);
9+
public partial record OmnibarPaletteSuggestionItem(string Title, string Description, string HotKeys)
10+
: IOmnibarTextMemberPathProvider
11+
{
12+
/// <inheritdoc/>
13+
public string GetTextMemberPath(string textMemberPath)
14+
{
15+
return textMemberPath switch
16+
{
17+
nameof(Title) => Title,
18+
nameof(Description) => Description,
19+
nameof(HotKeys) => HotKeys,
20+
_ => throw new ArgumentOutOfRangeException(nameof(textMemberPath), textMemberPath, null),
21+
};
22+
}
23+
}
724
}

tests/Files.App.UITests/Views/OmnibarPage.xaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
</controls:OmnibarMode>
5151

5252
<controls:OmnibarMode
53-
DisplayMemberPath="Title"
53+
DisplayMemberPath="{x:Bind Omnibar1_TextMemberPathForPaletteMode}"
5454
IconOnActive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Commands}, IsFilled=True}"
5555
IconOnInactive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Commands}, IconType=Outline}"
5656
ModeName="Palette"

tests/Files.App.UITests/Views/OmnibarPage.xaml.cs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Files.App.UITests.Views
1212
{
1313
public sealed partial class OmnibarPage : Page
1414
{
15+
private readonly string Omnibar1_TextMemberPathForPaletteMode = nameof(OmnibarPaletteSuggestionItem.Title);
16+
1517
private readonly ObservableCollection<OmnibarPaletteSuggestionItem> Omnibar1_PaletteSuggestions;
1618
private readonly ObservableCollection<BreadcrumbBarItemModel> Omnibar1_BreadcrumbBarItems;
1719

0 commit comments

Comments
 (0)