mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-30 02:47:45 +08:00
loading masker 完成
This commit is contained in:
parent
90e288a33c
commit
bdc74533f2
@ -28,16 +28,65 @@
|
||||
Title="Custom spinning indicator"
|
||||
Description="Use custom loading indicator.">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<atom:LoadingIndicator SizeType="Small"
|
||||
<atom:LoadingIndicator SizeType="Small"
|
||||
VerticalAlignment="Center"
|
||||
CustomIndicatorIcon="{atom:IconProvider Kind=LoadingOutlined,NormalFilledColor=#1677ff}"/>
|
||||
<atom:LoadingIndicator SizeType="Middle"
|
||||
<atom:LoadingIndicator SizeType="Middle"
|
||||
VerticalAlignment="Center"
|
||||
CustomIndicatorIcon="{atom:IconProvider Kind=LoadingOutlined,NormalFilledColor=#1677ff}"/>
|
||||
<atom:LoadingIndicator SizeType="Large"
|
||||
<atom:LoadingIndicator SizeType="Large"
|
||||
VerticalAlignment="Center"
|
||||
CustomIndicatorIcon="{atom:IconProvider Kind=LoadingOutlined,NormalFilledColor=#1677ff}"/>
|
||||
</StackPanel>
|
||||
</showcase:ShowCaseItem>
|
||||
|
||||
<showcase:ShowCaseItem
|
||||
Title="Customized description"
|
||||
Description="Customized description">
|
||||
<StackPanel Orientation="Vertical" Spacing="10">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<atom:LoadingMaskHost IsLoading="True" SizeType="Small"
|
||||
IsShowLoadingMsg="True"
|
||||
LoadingMsg="Loading...">
|
||||
<Border Width="100" Height="100" Background="rgb(251, 251, 251)" />
|
||||
</atom:LoadingMaskHost>
|
||||
<atom:LoadingMaskHost IsLoading="True" SizeType="Middle"
|
||||
IsShowLoadingMsg="True"
|
||||
LoadingMsg="Loading...">
|
||||
<Border Width="100" Height="100" Background="rgb(251, 251, 251)"/>
|
||||
</atom:LoadingMaskHost>
|
||||
<atom:LoadingMaskHost IsLoading="True" SizeType="Large"
|
||||
IsShowLoadingMsg="True"
|
||||
LoadingMsg="Loading...">
|
||||
<Border Width="100" Height="100" Background="rgb(251, 251, 251)"/>
|
||||
</atom:LoadingMaskHost>
|
||||
</StackPanel>
|
||||
<atom:LoadingMaskHost IsLoading="True"
|
||||
IsShowLoadingMsg="True"
|
||||
LoadingMsg="Loading...">
|
||||
<atom:Alert Message="Alert message title"
|
||||
Description="Further details about the context of this alert."
|
||||
Type="Info"/>
|
||||
</atom:LoadingMaskHost>
|
||||
</StackPanel>
|
||||
</showcase:ShowCaseItem>
|
||||
|
||||
<showcase:ShowCaseItem
|
||||
Title="Customized description"
|
||||
Description="Customized description">
|
||||
<StackPanel Orientation="Vertical" Spacing="10">
|
||||
<atom:LoadingMaskHost IsLoading="{Binding IsLoadingSwitchChecked}"
|
||||
IsShowLoadingMsg="True"
|
||||
LoadingMsg="Loading...">
|
||||
<atom:Alert Message="Alert message title"
|
||||
Description="Further details about the context of this alert."
|
||||
Type="Info"/>
|
||||
</atom:LoadingMaskHost>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<TextBlock>Loading state:</TextBlock>
|
||||
<atom:ToggleSwitch IsChecked="{Binding IsLoadingSwitchChecked}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</showcase:ShowCaseItem>
|
||||
</showcase:ShowCasePanel>
|
||||
</UserControl>
|
@ -1,11 +1,22 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace AtomUI.Demo.Desktop.ShowCase;
|
||||
|
||||
public partial class LoadingIndicatorShowCase : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<bool> IsLoadingSwitchCheckedProperty =
|
||||
AvaloniaProperty.Register<ProgressBarShowCase, bool>(nameof(IsLoadingSwitchChecked), false);
|
||||
|
||||
public bool IsLoadingSwitchChecked
|
||||
{
|
||||
get => GetValue(IsLoadingSwitchCheckedProperty);
|
||||
set => SetValue(IsLoadingSwitchCheckedProperty, value);
|
||||
}
|
||||
|
||||
public LoadingIndicatorShowCase()
|
||||
{
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
8
src/AtomUI.Controls/ICornerRadiusInfoProvider.cs
Normal file
8
src/AtomUI.Controls/ICornerRadiusInfoProvider.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Avalonia;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public interface ICornerRadiusInfoProvider
|
||||
{
|
||||
public CornerRadius CornerRadius { get; }
|
||||
}
|
@ -274,6 +274,7 @@ public partial class LoadingIndicator : Control, ISizeTypeAware, IControlCustomS
|
||||
_controlTokenBinder.AddControlBinding(FontSizeTokenProperty, GlobalResourceKey.FontSize);
|
||||
_controlTokenBinder.AddControlBinding(MarginXXSTokenProperty, GlobalResourceKey.MarginXXS);
|
||||
_controlTokenBinder.AddControlBinding(ColorPrimaryTokenProperty, GlobalResourceKey.ColorPrimary);
|
||||
_controlTokenBinder.AddControlBinding(_textBlock!, TextBlock.ForegroundProperty, GlobalResourceKey.ColorPrimary);
|
||||
}
|
||||
|
||||
private void BuildIndicatorAnimation(bool force = false)
|
||||
@ -369,14 +370,14 @@ public partial class LoadingIndicator : Control, ISizeTypeAware, IControlCustomS
|
||||
|
||||
var rightItemOffset = new Point(indicatorRect.Right - itemEdgeMargin - itemSize, centerPoint.Y - itemSize / 2);
|
||||
var bottomItemOffset = new Point(centerPoint.X - itemSize / 2, indicatorRect.Bottom - itemEdgeMargin - itemSize);
|
||||
var leftItemOffset = new Point(itemEdgeMargin, centerPoint.Y - itemSize / 2);
|
||||
var topItemOffset = new Point(centerPoint.X - itemSize / 2, itemEdgeMargin);
|
||||
var leftItemOffset = new Point(indicatorRect.Left + itemEdgeMargin, centerPoint.Y - itemSize / 2);
|
||||
var topItemOffset = new Point(centerPoint.X - itemSize / 2, indicatorRect.Top + itemEdgeMargin);
|
||||
|
||||
var matrix = Matrix.CreateTranslation(-indicatorRect.Center.X, -indicatorRect.Center.Y);
|
||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(IndicatorAngle));
|
||||
matrix *= Matrix.CreateTranslation(indicatorRect.Center.X, indicatorRect.Center.Y);
|
||||
using var translateState = context.PushTransform(matrix);
|
||||
|
||||
|
||||
{
|
||||
using var opacityState = context.PushOpacity(rightItemOpacity);
|
||||
var itemRect = new Rect(rightItemOffset, new Size(itemSize, itemSize));
|
||||
|
61
src/AtomUI.Controls/Loading/LoadingIndicatorAdorner.cs
Normal file
61
src/AtomUI.Controls/Loading/LoadingIndicatorAdorner.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using AtomUI.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class LoadingIndicatorAdorner : Control, IControlCustomStyle
|
||||
{
|
||||
private bool _initialized = false;
|
||||
private IControlCustomStyle _customStyle;
|
||||
private LoadingIndicator? _loadingIndicator;
|
||||
|
||||
public EventHandler<LoadingIndicatorCreatedEventArgs>? IndicatorCreated;
|
||||
|
||||
public LoadingIndicatorAdorner()
|
||||
{
|
||||
_customStyle = this;
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
if (!_initialized) {
|
||||
_customStyle.SetupUi();
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void IControlCustomStyle.SetupUi()
|
||||
{
|
||||
_loadingIndicator = new LoadingIndicator();
|
||||
IndicatorCreated?.Invoke(this, new LoadingIndicatorCreatedEventArgs(_loadingIndicator));
|
||||
LogicalChildren.Add(_loadingIndicator);
|
||||
VisualChildren.Add(_loadingIndicator);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var offsetX = (finalSize.Width - _loadingIndicator!.DesiredSize.Width) / 2;
|
||||
var offsetY = (finalSize.Height - _loadingIndicator.DesiredSize.Height) / 2;
|
||||
_loadingIndicator.Arrange(new Rect(new Point(offsetX, offsetY), _loadingIndicator.DesiredSize));
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
base.MeasureOverride(availableSize);
|
||||
return availableSize;
|
||||
}
|
||||
}
|
||||
|
||||
public class LoadingIndicatorCreatedEventArgs : EventArgs
|
||||
{
|
||||
public LoadingIndicator LoadingIndicator { get; set; }
|
||||
|
||||
public LoadingIndicatorCreatedEventArgs(LoadingIndicator indicator)
|
||||
{
|
||||
LoadingIndicator = indicator;
|
||||
}
|
||||
}
|
@ -1,6 +1,175 @@
|
||||
namespace AtomUI.Controls;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
|
||||
public class LoadingMask
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class LoadingMask : AvaloniaObject, IDisposable
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
LoadingIndicator.SizeTypeProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public static readonly StyledProperty<string?> LoadingMsgProperty =
|
||||
LoadingIndicator.LoadingMsgProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowLoadingMsgProperty =
|
||||
LoadingIndicator.IsShowLoadingMsgProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public static readonly StyledProperty<PathIcon?> CustomIndicatorIconProperty =
|
||||
LoadingIndicator.CustomIndicatorIconProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public static readonly StyledProperty<TimeSpan?> MotionDurationProperty =
|
||||
LoadingIndicator.MotionDurationProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public static readonly StyledProperty<Easing?> MotionEasingCurveProperty =
|
||||
LoadingIndicator.MotionEasingCurveProperty.AddOwner<LoadingMask>();
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
|
||||
public string? LoadingMsg
|
||||
{
|
||||
get => GetValue(LoadingMsgProperty);
|
||||
set => SetValue(LoadingMsgProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowLoadingMsg
|
||||
{
|
||||
get => GetValue(IsShowLoadingMsgProperty);
|
||||
set => SetValue(IsShowLoadingMsgProperty, value);
|
||||
}
|
||||
|
||||
public PathIcon? CustomIndicatorIcon
|
||||
{
|
||||
get => GetValue(CustomIndicatorIconProperty);
|
||||
set => SetValue(CustomIndicatorIconProperty, value);
|
||||
}
|
||||
|
||||
public TimeSpan? MotionDuration
|
||||
{
|
||||
get => GetValue(MotionDurationProperty);
|
||||
set => SetValue(MotionDurationProperty, value);
|
||||
}
|
||||
|
||||
public Easing? MotionEasingCurve
|
||||
{
|
||||
get => GetValue(MotionEasingCurveProperty);
|
||||
set => SetValue(MotionEasingCurveProperty, value);
|
||||
}
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Control? _attachTarget;
|
||||
private LoadingIndicatorAdorner? _loadingIndicatorAdorner;
|
||||
private AdornerLayer? _adornerLayer;
|
||||
|
||||
public LoadingMask(Control? attachTarget = null)
|
||||
{
|
||||
if (attachTarget is not null) {
|
||||
Attach(attachTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public void Attach(Control attachTarget)
|
||||
{
|
||||
if (_attachTarget is not null) {
|
||||
Detach();
|
||||
}
|
||||
|
||||
attachTarget.DetachedFromLogicalTree += HandleTargetDetachedFromVisualTree;
|
||||
_attachTarget = attachTarget;
|
||||
}
|
||||
|
||||
public void Detach()
|
||||
{
|
||||
if (_attachTarget is null) {
|
||||
return;
|
||||
}
|
||||
Hide();
|
||||
_attachTarget.DetachedFromLogicalTree -= HandleTargetDetachedFromVisualTree;
|
||||
_attachTarget = null;
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
if (_attachTarget is null || IsLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_adornerLayer is null) {
|
||||
_adornerLayer = AdornerLayer.GetAdornerLayer(_attachTarget);
|
||||
if (_adornerLayer == null) {
|
||||
throw new SystemException("No Adorner Layer found.");
|
||||
}
|
||||
}
|
||||
|
||||
_loadingIndicatorAdorner ??= new LoadingIndicatorAdorner();
|
||||
_loadingIndicatorAdorner.IndicatorCreated += HandleLoadingIndicatorCreated;
|
||||
|
||||
// 尽力探测 cornerradius
|
||||
_attachTarget.Effect = new BlurEffect()
|
||||
{
|
||||
Radius = 5
|
||||
};
|
||||
AdornerLayer.SetAdornedElement(_loadingIndicatorAdorner, _attachTarget);
|
||||
AdornerLayer.SetIsClipEnabled(_loadingIndicatorAdorner, true);
|
||||
_adornerLayer.Children.Add(_loadingIndicatorAdorner);
|
||||
|
||||
IsLoading = true;
|
||||
}
|
||||
|
||||
// 在这里进行配置
|
||||
private void HandleLoadingIndicatorCreated(object? sender, LoadingIndicatorCreatedEventArgs args)
|
||||
{
|
||||
var indicator = args.LoadingIndicator;
|
||||
BindUtils.RelayBind(this, SizeTypeProperty, indicator, SizeTypeProperty);
|
||||
BindUtils.RelayBind(this, LoadingMsgProperty, indicator, LoadingMsgProperty);
|
||||
BindUtils.RelayBind(this, IsShowLoadingMsgProperty, indicator, IsShowLoadingMsgProperty);
|
||||
BindUtils.RelayBind(this, CustomIndicatorIconProperty, indicator, CustomIndicatorIconProperty);
|
||||
BindUtils.RelayBind(this, MotionDurationProperty, indicator, MotionDurationProperty);
|
||||
BindUtils.RelayBind(this, MotionEasingCurveProperty, indicator, MotionEasingCurveProperty);
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
if (!IsLoading || _attachTarget is null) {
|
||||
return;
|
||||
}
|
||||
if (_adornerLayer is not null && _loadingIndicatorAdorner is not null) {
|
||||
_adornerLayer.Children.Remove(_loadingIndicatorAdorner);
|
||||
}
|
||||
|
||||
_attachTarget.Effect = null;
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_attachTarget is not null) {
|
||||
Detach();
|
||||
}
|
||||
|
||||
_adornerLayer = null;
|
||||
_loadingIndicatorAdorner = null;
|
||||
}
|
||||
|
||||
private void HandleTargetDetachedFromVisualTree(object? sender, LogicalTreeAttachmentEventArgs args)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
173
src/AtomUI.Controls/Loading/LoadingMaskHost.cs
Normal file
173
src/AtomUI.Controls/Loading/LoadingMaskHost.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class LoadingMaskHost : Control, IControlCustomStyle
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
LoadingIndicator.SizeTypeProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<string?> LoadingMsgProperty =
|
||||
LoadingIndicator.LoadingMsgProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowLoadingMsgProperty =
|
||||
LoadingIndicator.IsShowLoadingMsgProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<PathIcon?> CustomIndicatorIconProperty =
|
||||
LoadingIndicator.CustomIndicatorIconProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<TimeSpan?> MotionDurationProperty =
|
||||
LoadingIndicator.MotionDurationProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<Easing?> MotionEasingCurveProperty =
|
||||
LoadingIndicator.MotionEasingCurveProperty.AddOwner<LoadingMaskHost>();
|
||||
|
||||
public static readonly StyledProperty<bool> IsLoadingProperty =
|
||||
AvaloniaProperty.Register<LoadingMaskHost, bool>(nameof(IsLoading), false);
|
||||
|
||||
public static readonly StyledProperty<Control?> MaskTargetProperty =
|
||||
AvaloniaProperty.Register<CountBadge, Control?>(nameof(MaskTarget));
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
|
||||
public string? LoadingMsg
|
||||
{
|
||||
get => GetValue(LoadingMsgProperty);
|
||||
set => SetValue(LoadingMsgProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowLoadingMsg
|
||||
{
|
||||
get => GetValue(IsShowLoadingMsgProperty);
|
||||
set => SetValue(IsShowLoadingMsgProperty, value);
|
||||
}
|
||||
|
||||
public PathIcon? CustomIndicatorIcon
|
||||
{
|
||||
get => GetValue(CustomIndicatorIconProperty);
|
||||
set => SetValue(CustomIndicatorIconProperty, value);
|
||||
}
|
||||
|
||||
public TimeSpan? MotionDuration
|
||||
{
|
||||
get => GetValue(MotionDurationProperty);
|
||||
set => SetValue(MotionDurationProperty, value);
|
||||
}
|
||||
|
||||
public Easing? MotionEasingCurve
|
||||
{
|
||||
get => GetValue(MotionEasingCurveProperty);
|
||||
set => SetValue(MotionEasingCurveProperty, value);
|
||||
}
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
|
||||
[Content]
|
||||
public Control? MaskTarget
|
||||
{
|
||||
get => GetValue(MaskTargetProperty);
|
||||
set => SetValue(MaskTargetProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private LoadingMask? _loadingMask;
|
||||
private bool _initialized = false;
|
||||
private IControlCustomStyle _customStyle;
|
||||
|
||||
public LoadingMaskHost()
|
||||
{
|
||||
_customStyle = this;
|
||||
}
|
||||
|
||||
void IControlCustomStyle.SetupUi()
|
||||
{
|
||||
if (MaskTarget is not null) {
|
||||
LogicalChildren.Add(MaskTarget);
|
||||
VisualChildren.Add(MaskTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowLoading()
|
||||
{
|
||||
if (_loadingMask is not null && _loadingMask.IsLoading) {
|
||||
return;
|
||||
}
|
||||
if (_loadingMask is null && MaskTarget is not null) {
|
||||
_loadingMask = new LoadingMask();
|
||||
_loadingMask.Attach(this);
|
||||
BindUtils.RelayBind(this, SizeTypeProperty, _loadingMask, SizeTypeProperty);
|
||||
BindUtils.RelayBind(this, LoadingMsgProperty, _loadingMask, LoadingMsgProperty);
|
||||
BindUtils.RelayBind(this, IsShowLoadingMsgProperty, _loadingMask, IsShowLoadingMsgProperty);
|
||||
BindUtils.RelayBind(this, CustomIndicatorIconProperty, _loadingMask, CustomIndicatorIconProperty);
|
||||
BindUtils.RelayBind(this, MotionDurationProperty, _loadingMask, MotionDurationProperty);
|
||||
BindUtils.RelayBind(this, MotionEasingCurveProperty, _loadingMask, MotionEasingCurveProperty);
|
||||
}
|
||||
_loadingMask!.Show();
|
||||
}
|
||||
|
||||
public void HideLoading()
|
||||
{
|
||||
if (_loadingMask is null ||
|
||||
(_loadingMask is not null && !_loadingMask.IsLoading)) {
|
||||
return;
|
||||
}
|
||||
_loadingMask?.Hide();
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
if (IsLoading && MaskTarget is not null) {
|
||||
ShowLoading();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
if (!_initialized) {
|
||||
_customStyle.SetupUi();
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
HideLoading();
|
||||
_loadingMask?.Dispose();
|
||||
_loadingMask = null;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (_initialized && VisualRoot is not null) {
|
||||
if (IsLoadingProperty == change.Property) {
|
||||
if (IsLoading) {
|
||||
ShowLoading();
|
||||
} else {
|
||||
HideLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user