Skip to content

Commit

Permalink
chore: Adjust apply template and SV
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 authored and Xiaoy312 committed Aug 2, 2024
1 parent 9fa1641 commit a589451
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 124 deletions.
28 changes: 26 additions & 2 deletions src/Uno.UI/UI/Xaml/Controls/AutoSuggestBox/AutoSuggestBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public partial class AutoSuggestBox : ItemsControl
private string _userInput;
private FrameworkElement _suggestionsContainer;
private IDisposable _textChangedDisposable;
private IDisposable _textBoxLoadedDisposable;

public AutoSuggestBox() : base()
{
Expand All @@ -52,7 +53,12 @@ protected override void OnApplyTemplate()
_layoutRoot = GetTemplateChild("LayoutRoot") as Grid;
_suggestionsList = GetTemplateChild("SuggestionsList") as ListView;
_suggestionsContainer = GetTemplateChild("SuggestionsContainer") as FrameworkElement;
_queryButton = GetTemplateChild("QueryButton") as Button;

// This is *expected* to be null on platforms with proper lifecycle.
// The queryButton is part of the TextBox template, which is not applied yet.
// On WinUI, QueryButton is never retrieved in OnTextBoxLoaded, not in OnApplyTemplate.
// We do in both to account for all our platforms.
_queryButton = _textBox?.GetTemplateChild("QueryButton") as Button;

// Uno specific: If the user enabled the legacy behavior for popup light dismiss default
// we force it to false explicitly to make sure the AutoSuggestBox works correctly.
Expand All @@ -72,15 +78,25 @@ protected override void OnApplyTemplate()
}
#endif

UpdateQueryButton();
UpdateTextBox();
UpdateDescriptionVisibility(true);

_textChangedDisposable?.Dispose();
_textBoxLoadedDisposable?.Dispose();
if (_textBox is { })
{
_textBox.TextChanged += OnTextBoxTextChanged;
_textChangedDisposable = Disposable.Create(() => _textBox.TextChanged -= OnTextBoxTextChanged);

if (_textBox.IsLoaded)
{
UpdateQueryButton();
}
else
{
_textBox.Loaded += OnTextBoxLoaded;
_textBoxLoadedDisposable = Disposable.Create(() => _textBox.Loaded -= OnTextBoxLoaded);
}
}

Loaded += (s, e) => RegisterEvents();
Expand All @@ -103,6 +119,11 @@ private void OnTextBoxTextChanged(object sender, TextChangedEventArgs args)
OnTextChanged(args.IsUserModifyingText);
}

private void OnTextBoxLoaded(object sender, RoutedEventArgs args)
{
UpdateQueryButton();
}

private void OnItemsChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
{
UpdateSuggestionList();
Expand Down Expand Up @@ -273,6 +294,7 @@ void RegisterEvents()
if (_textBox != null)
{
_textBox.KeyDown += OnTextBoxKeyDown;
_queryButton = _textBox.GetTemplateChild<Button>("QueryButton");
}

if (_queryButton != null)
Expand All @@ -295,6 +317,7 @@ void RegisterEvents()
void UnregisterEvents()
{
_textChangedDisposable?.Dispose();
_textBoxLoadedDisposable?.Dispose();
if (_textBox != null)
{
_textBox.KeyDown -= OnTextBoxKeyDown;
Expand Down Expand Up @@ -344,6 +367,7 @@ private void OnIsSuggestionListOpenChanged(DependencyPropertyChangedEventArgs e)

private void UpdateQueryButton()
{
_queryButton = _textBox?.GetTemplateChild<Button>("QueryButton");
if (_queryButton == null)
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private void Initialize_CalendarViewBaseItemChrome()
m_hasLabel = false;
}

private bool HasTemplateChild()
private protected override bool HasTemplateChild()
{
return GetFirstChildNoAddRef() != null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ protected virtual void OnContentTemplateChanged(DataTemplate oldContentTemplate,
}
else if (CanCreateTemplateWithoutParent)
{
SetUpdateControlTemplate();
ApplyTemplate();
}
}

Expand Down
97 changes: 18 additions & 79 deletions src/Uno.UI/UI/Xaml/Controls/Control/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public partial class Control : FrameworkElement
{
private bool _suspendStateChanges;
private View _templatedRoot;
private bool _updateTemplate;
private bool _suppressIsEnabled;

private void InitializeControl()
Expand Down Expand Up @@ -88,11 +87,6 @@ private protected virtual void ChangeVisualState(bool useTransitions)
{
}

/// <summary>
/// Will be set to Template when it is applied
/// </summary>
private ControlTemplate _controlTemplateUsedLastUpdate;

partial void UnregisterSubView();
partial void RegisterSubView(View child);

Expand Down Expand Up @@ -206,36 +200,18 @@ public ControlTemplate Template

// Using a DependencyProperty as the backing store for Template. This enables animation, styling, binding, etc...
public static DependencyProperty TemplateProperty { get; } =
DependencyProperty.Register("Template", typeof(ControlTemplate), typeof(Control), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext, (s, e) => ((Control)s)?.OnTemplateChanged(e)));
DependencyProperty.Register("Template", typeof(ControlTemplate), typeof(Control), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext | FrameworkPropertyMetadataOptions.AffectsMeasure, (s, e) => ((Control)s)?.OnTemplateChanged(e)));

private void OnTemplateChanged(DependencyPropertyChangedEventArgs e)
private protected virtual void OnTemplateChanged(DependencyPropertyChangedEventArgs e)
{
#if !UNO_HAS_ENHANCED_LIFECYCLE
_updateTemplate = true;
SetUpdateControlTemplate();
#endif
}

#endregion

/// <summary>
/// Defines a method that will request the update of the control's template and request layout update.
/// </summary>
/// <param name="forceUpdate">If true, forces an update even if the control has no parent.</param>
internal void SetUpdateControlTemplate(bool forceUpdate = false)
{
if (
#if !UNO_HAS_ENHANCED_LIFECYCLE
!FeatureConfiguration.Control.UseLegacyLazyApplyTemplate ||
#endif
forceUpdate ||
this.HasParent() ||
CanCreateTemplateWithoutParent
)
{
UpdateTemplate();
this.InvalidateMeasure();
}
}

/// <summary>
/// Represents the single child that is the result of the control template application.
/// </summary>
Expand All @@ -251,10 +227,12 @@ internal View TemplatedRoot

CleanupView(_templatedRoot);

#if !UNO_HAS_ENHANCED_LIFECYCLE
UnregisterSubView();
#endif

_templatedRoot = value;

#if !UNO_HAS_ENHANCED_LIFECYCLE
if (value != null)
{
RegisterSubView(value);
Expand All @@ -264,9 +242,6 @@ internal View TemplatedRoot
RegisterContentTemplateRoot();

if (
#if __CROSSRUNTIME__
!IsLoading &&
#endif
!IsLoaded && FeatureConfiguration.Control.UseDeferredOnApplyTemplate)
{
// It's too soon the call the ".OnApplyTemplate" method: it should be invoked after the "Loading" event.
Expand All @@ -291,11 +266,10 @@ internal View TemplatedRoot
}
}
}
#endif
}
}

private bool _applyTemplateShouldBeInvoked;

#if __ANDROID__ || __IOS__ || __MACOS__ || IS_UNIT_TESTS
private protected override void OnPostLoading()
{
Expand All @@ -309,15 +283,6 @@ private protected override void OnPostLoading()
}
#endif

internal void TryCallOnApplyTemplate()
{
if (_applyTemplateShouldBeInvoked)
{
_applyTemplateShouldBeInvoked = false;
OnApplyTemplate();
}
}

private void SubscribeToOverridenRoutedEvents()
{
// Overridden Events are registered from constructor to ensure they are
Expand Down Expand Up @@ -456,10 +421,11 @@ private void SubscribeToOverridenRoutedEvents()

private protected override void OnLoaded()
{
#if !UNO_HAS_ENHANCED_LIFECYCLE
SetUpdateControlTemplate();
#endif

base.OnLoaded();

}

protected override Size MeasureOverride(Size availableSize)
Expand All @@ -482,20 +448,19 @@ protected override Size MeasureOverride(Size availableSize)
protected override Size ArrangeOverride(Size finalSize)
=> ArrangeFirstChild(finalSize);

#if UNO_HAS_ENHANCED_LIFECYCLE
/// <summary>
/// Loads the relevant control template so that its parts can be referenced.
/// </summary>
/// <returns>A value that indicates whether the visual tree was rebuilt by this call. True if the tree was rebuilt; false if the previous visual tree was retained.</returns>
public bool ApplyTemplate()
{
var currentTemplateRoot = _templatedRoot;
SetUpdateControlTemplate(forceUpdate: true);

// When .ApplyTemplate is called manually, we should not defer the call to OnApplyTemplate
TryCallOnApplyTemplate();

return currentTemplateRoot != _templatedRoot;
InvokeApplyTemplate(out var addedVisuals);
return addedVisuals;
}
#endif

private protected override FrameworkTemplate GetTemplate() => Template;

/// <summary>
/// Applies default Style and implicit/explicit Style if not applied already, and materializes template.
Expand Down Expand Up @@ -566,42 +531,16 @@ protected override void OnVisibilityChanged(Visibility oldValue, Visibility newV
{
base.OnVisibilityChanged(oldValue, newValue);

#if !UNO_HAS_ENHANCED_LIFECYCLE
if (oldValue == Visibility.Collapsed && newValue == Visibility.Visible)
{
SetUpdateControlTemplate();
}
#endif

OnIsFocusableChanged();
}

private void UpdateTemplate()
{
// If TemplatedRoot is null, it must be updated even if the templates haven't changed
if (TemplatedRoot == null)
{
_controlTemplateUsedLastUpdate = null;
}

if (_updateTemplate && !object.Equals(Template, _controlTemplateUsedLastUpdate))
{
_controlTemplateUsedLastUpdate = Template;

if (Template != null)
{
TemplatedRoot = null;
UnregisterSubView();

TemplatedRoot = Template.LoadContentCached(this);
}
else
{
TemplatedRoot = null;
}

_updateTemplate = false;
}
}

partial void RegisterContentTemplateRoot();

#region Foreground Dependency Property
Expand Down
82 changes: 82 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Control/Control.nonlifecycle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#if !UNO_HAS_ENHANCED_LIFECYCLE
namespace Microsoft.UI.Xaml.Controls;

partial class Control
{
private bool _updateTemplate;

/// <summary>
/// Will be set to Template when it is applied
/// </summary>
private ControlTemplate _controlTemplateUsedLastUpdate;

private bool _applyTemplateShouldBeInvoked;

/// <summary>
/// Defines a method that will request the update of the control's template and request layout update.
/// </summary>
/// <param name="forceUpdate">If true, forces an update even if the control has no parent.</param>
internal void SetUpdateControlTemplate(bool forceUpdate = false)
{
if (
!FeatureConfiguration.Control.UseLegacyLazyApplyTemplate ||
forceUpdate ||
this.HasParent() ||
CanCreateTemplateWithoutParent
)
{
UpdateTemplate();
this.InvalidateMeasure();
}
}

internal void TryCallOnApplyTemplate()
{
if (_applyTemplateShouldBeInvoked)
{
_applyTemplateShouldBeInvoked = false;
OnApplyTemplate();
}
}

/// <summary>
/// Loads the relevant control template so that its parts can be referenced.
/// </summary>
/// <returns>A value that indicates whether the visual tree was rebuilt by this call. True if the tree was rebuilt; false if the previous visual tree was retained.</returns>
public bool ApplyTemplate()
{
var currentTemplateRoot = _templatedRoot;
SetUpdateControlTemplate(forceUpdate: true);

// When .ApplyTemplate is called manually, we should not defer the call to OnApplyTemplate
TryCallOnApplyTemplate();

return currentTemplateRoot != _templatedRoot;
}

private void UpdateTemplate()
{
// If TemplatedRoot is null, it must be updated even if the templates haven't changed
if (TemplatedRoot == null)
{
_controlTemplateUsedLastUpdate = null;
}

if (_updateTemplate && !object.Equals(Template, _controlTemplateUsedLastUpdate))
{
_controlTemplateUsedLastUpdate = Template;

if (Template != null)
{
TemplatedRoot = Template.LoadContentCached();
}
else
{
TemplatedRoot = null;
}

_updateTemplate = false;
}
}
}
#endif
Loading

0 comments on commit a589451

Please sign in to comment.