From 232016e6ceda23fcb328bcff77f1666ca97c1c04 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Levesque Date: Fri, 6 Jun 2025 15:00:20 -0400 Subject: [PATCH] fix: Ensure visual states are applied even when the DataLoader gets its data before the control template is applied. --- src/DataLoader.Uno.Shared/DataLoaderView.cs | 7 +++++++ .../DataLoaderViewControllerBase.cs | 15 +++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/DataLoader.Uno.Shared/DataLoaderView.cs b/src/DataLoader.Uno.Shared/DataLoaderView.cs index 1c82610..29b8603 100644 --- a/src/DataLoader.Uno.Shared/DataLoaderView.cs +++ b/src/DataLoader.Uno.Shared/DataLoaderView.cs @@ -55,6 +55,13 @@ private void OnUnloaded(object sender, RoutedEventArgs e) _controller.OnViewUnloaded(); } + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _controller.OnControlTemplateApplied(); + } + private void OnSourceChanged(IDataLoader dataLoader) { _controller.SetDataLoader(dataLoader); diff --git a/src/DataLoader.Uno.Shared/DataLoaderViewControllerBase.cs b/src/DataLoader.Uno.Shared/DataLoaderViewControllerBase.cs index a47a49f..2f1d09e 100644 --- a/src/DataLoader.Uno.Shared/DataLoaderViewControllerBase.cs +++ b/src/DataLoader.Uno.Shared/DataLoaderViewControllerBase.cs @@ -51,6 +51,7 @@ public abstract class DataLoaderViewControllerBase private IDataLoaderState _lastState; private DataLoaderViewState _lastViewState; private bool _isLoaded; + private bool _isControlTemplateApplied; private bool _isSubscribedToSource; private bool _isVisualStateRefreshRequired; private DateTimeOffset _lastUpdate = DateTimeOffset.MinValue; // This is a timestamp of when the last UI update was done. @@ -145,6 +146,12 @@ public void OnViewUnloaded() _isLoaded = false; } + public void OnControlTemplateApplied() + { + _isControlTemplateApplied = true; + Update(_dataLoader?.State); + } + private void OnDataLoaderStateChanged(IDataLoader dataLoader, IDataLoaderState newState) { Update(newState); @@ -190,7 +197,7 @@ private async void Update(IDataLoaderState newState, [CallerMemberName] string s if (Object.Equals(_nextState, _lastState)) { // When the states are equal, we usually skip the update, unless a visual state refresh is required. (That happens when the DataLoader changes state before the DataLoaderView is Loaded.) - if (_isVisualStateRefreshRequired && _isLoaded) + if (_isVisualStateRefreshRequired && _isLoaded && _isControlTemplateApplied) { await RunOnDispatcher(() => { @@ -288,7 +295,7 @@ private void UpdateUI(IDataLoaderState newState) var combinedVisualState = $"{dataVisualState}_{errorVisualState}_{loadingVisualState}"; GoToState(view, CombinedVisualGroup, combinedVisualState); - if (_isLoaded) + if (_isLoaded && _isControlTemplateApplied) { _isVisualStateRefreshRequired = false; @@ -395,7 +402,7 @@ private void GoToState(Control control, string group, string visualState, bool u if (currentState != visualState) { _currentGroupStates[group] = visualState; - if (_isLoaded) + if (_isLoaded && _isControlTemplateApplied) { VisualStateManager.GoToState(control, visualState, useTransitions); } @@ -404,7 +411,7 @@ private void GoToState(Control control, string group, string visualState, bool u else { _currentGroupStates[group] = visualState; - if (_isLoaded) + if (_isLoaded && _isControlTemplateApplied) { VisualStateManager.GoToState(control, visualState, useTransitions); }