diff --git a/src/AtomUI.Controls/Card/Card.cs b/src/AtomUI.Controls/Card/Card.cs index 4706c26da..e6b006904 100644 --- a/src/AtomUI.Controls/Card/Card.cs +++ b/src/AtomUI.Controls/Card/Card.cs @@ -70,9 +70,6 @@ public class Card : HeaderedContentControl, public static readonly StyledProperty CoverTemplateProperty = AvaloniaProperty.Register(nameof (CoverTemplate)); - public static readonly StyledProperty> ActionsProperty = - AvaloniaProperty.Register>(nameof (Actions), new List()); - public static readonly StyledProperty IsMotionEnabledProperty = MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner(); @@ -236,7 +233,7 @@ public class Card : HeaderedContentControl, public Card() { this.RegisterResources(); - Actions.CollectionChanged += new NotifyCollectionChangedEventHandler(this.HandleActionsChanged); + Actions.CollectionChanged += new NotifyCollectionChangedEventHandler(HandleActionsChanged); } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) @@ -281,9 +278,12 @@ public class Card : HeaderedContentControl, { SetCurrentValue(ContentTypeProperty, CardContentType.Meta); } - else if (Content is CardTabsContent) + else if (Content is CardTabsContent cardTabsContent) { SetCurrentValue(ContentTypeProperty, CardContentType.Tabs); + _contentBindingDisposables = new CompositeDisposable(); + _contentBindingDisposables.Add(BindUtils.RelayBind(this, IsMotionEnabledProperty, cardTabsContent, CardTabsContent.IsMotionEnabledProperty)); + _contentBindingDisposables.Add(BindUtils.RelayBind(this, SizeTypeProperty, cardTabsContent, CardTabsContent.SizeTypeProperty)); } else if (Content is CardGridContent cardGridContent) { diff --git a/src/AtomUI.Controls/Card/CardGridContent.cs b/src/AtomUI.Controls/Card/CardGridContent.cs index 88b024f3b..17363a5b8 100644 --- a/src/AtomUI.Controls/Card/CardGridContent.cs +++ b/src/AtomUI.Controls/Card/CardGridContent.cs @@ -2,13 +2,10 @@ using System.Collections.Specialized; using System.Reactive.Disposables; using AtomUI.Controls.Themes; using AtomUI.Data; -using AtomUI.Theme.Data; -using AtomUI.Theme.Styling; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; -using Avalonia.Data; namespace AtomUI.Controls; diff --git a/src/AtomUI.Controls/Card/CardGridItem.cs b/src/AtomUI.Controls/Card/CardGridItem.cs index dcc446486..50ddaa0db 100644 --- a/src/AtomUI.Controls/Card/CardGridItem.cs +++ b/src/AtomUI.Controls/Card/CardGridItem.cs @@ -25,6 +25,9 @@ public class CardGridItem : ContentControl public static readonly StyledProperty ColumnSpanProperty = AvaloniaProperty.Register(nameof (ColumnSpan)); + public static readonly StyledProperty IsHoverableProperty = + AvaloniaProperty.Register(nameof (IsHoverable), true); + public BoxShadows BoxShadow { get => GetValue(BoxShadowProperty); @@ -55,6 +58,12 @@ public class CardGridItem : ContentControl set => SetValue(ColumnSpanProperty, value); } + public bool IsHoverable + { + get => GetValue(IsHoverableProperty); + set => SetValue(IsHoverableProperty, value); + } + #region 内部属性定义 public static readonly StyledProperty SizeTypeProperty = diff --git a/src/AtomUI.Controls/Card/CardTabsContent.cs b/src/AtomUI.Controls/Card/CardTabsContent.cs index b5618a5be..58a0bb798 100644 --- a/src/AtomUI.Controls/Card/CardTabsContent.cs +++ b/src/AtomUI.Controls/Card/CardTabsContent.cs @@ -1,17 +1,30 @@ +using System.Collections; +using System.Collections.Specialized; +using AtomUI.Controls.Themes; using Avalonia; +using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Metadata; namespace AtomUI.Controls; +using ControlList = Avalonia.Controls.Controls; + public class CardTabsContent : TemplatedControl { #region 公共属性定义 public static readonly StyledProperty TabBarExtraContentProperty = - AvaloniaProperty.Register(nameof (TabBarExtraContent)); + AvaloniaProperty.Register(nameof (TabBarExtraContent)); public static readonly StyledProperty TabBarExtraContentTemplateProperty = - AvaloniaProperty.Register(nameof (TabBarExtraContentTemplate)); + AvaloniaProperty.Register(nameof (TabBarExtraContentTemplate)); + + public static readonly StyledProperty TabItemsSourceProperty = + AvaloniaProperty.Register(nameof (TabItemsSource)); + + public static readonly StyledProperty TabItemTemplateProperty = + AvaloniaProperty.Register(nameof (TabItemTemplate)); public object? TabBarExtraContent { @@ -24,5 +37,130 @@ public class CardTabsContent : TemplatedControl get => GetValue(TabBarExtraContentTemplateProperty); set => SetValue(TabBarExtraContentTemplateProperty, value); } + + public IEnumerable? TabItemsSource + { + get => GetValue(TabItemsSourceProperty); + set => SetValue(TabItemsSourceProperty, value); + } + + [InheritDataTypeFromItems(nameof(TabItemsSource))] + public IDataTemplate? TabItemTemplate + { + get => GetValue(TabItemTemplateProperty); + set => SetValue(TabItemTemplateProperty, value); + } #endregion + + #region 内部属性定义 + + internal static readonly StyledProperty SizeTypeProperty = + SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner(); + + internal static readonly StyledProperty IsMotionEnabledProperty = + MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner(); + + public SizeType SizeType + { + get => GetValue(SizeTypeProperty); + set => SetValue(SizeTypeProperty, value); + } + + internal bool IsMotionEnabled + { + get => GetValue(IsMotionEnabledProperty); + set => SetValue(IsMotionEnabledProperty, value); + } + + #endregion + + private readonly ControlList _items = new ControlList(); + private TabControl? _tabControl; + + [Content] + public ControlList Items => _items; + + public CardTabsContent() + { + Items.CollectionChanged += new NotifyCollectionChangedEventHandler(HandleTabsChanged); + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + _tabControl = e.NameScope.Find(CardTabsContentThemeConstants.TabControlPart); + if (_tabControl != null) + { + foreach (var tabItem in Items) + { + _tabControl.Items.Add(tabItem); + } + } + } + + private void HandleTabsChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + if (_tabControl != null) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + var newItems = e.NewItems!.OfType(); + var newStartingIndex = e.NewStartingIndex; + foreach (var control in newItems) + { + _tabControl.Items.Insert(newStartingIndex++, control); + } + + break; + case NotifyCollectionChangedAction.Remove: + foreach (var control in e.OldItems!.OfType()) + { + _tabControl.Items.Remove(control); + } + break; + case NotifyCollectionChangedAction.Replace: + for (int index1 = 0; index1 < e.OldItems!.Count; ++index1) + { + int index2 = index1 + e.OldStartingIndex; + Control newItem = (Control) e.NewItems![index1]!; + _tabControl.Items[index2] = newItem; + } + break; + case NotifyCollectionChangedAction.Move: + var oldIndex = e.OldStartingIndex; + var count = e.OldItems!.Count; + List oldItems = new List(); + for (int i = oldIndex; i < count; ++i) + { + var oldItem = e.OldItems![i]; + if (oldItem is Control control) + { + oldItems.Add(control); + } + } + + var newIndex = e.NewStartingIndex; + int index = newIndex; + for (int i = oldIndex; i < count; ++i) + { + _tabControl.Items.RemoveAt(index); + } + + if (newIndex > oldIndex) + { + index -= count - 1; + } + + foreach (var control in oldItems) + { + _tabControl.Items.Insert(index++, control); + } + + break; + case NotifyCollectionChangedAction.Reset: + throw new NotSupportedException(); + } + } + } } \ No newline at end of file diff --git a/src/AtomUI.Controls/Card/Themes/CardGridItemTheme.axaml b/src/AtomUI.Controls/Card/Themes/CardGridItemTheme.axaml index 5aa1eccc0..bc033a262 100644 --- a/src/AtomUI.Controls/Card/Themes/CardGridItemTheme.axaml +++ b/src/AtomUI.Controls/Card/Themes/CardGridItemTheme.axaml @@ -13,14 +13,14 @@ Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" - VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> + VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" /> - - - + + + - - \ No newline at end of file diff --git a/src/AtomUI.Controls/Card/Themes/CardTabsContentTheme.axaml b/src/AtomUI.Controls/Card/Themes/CardTabsContentTheme.axaml index fb664e6ed..d3eaf93a0 100644 --- a/src/AtomUI.Controls/Card/Themes/CardTabsContentTheme.axaml +++ b/src/AtomUI.Controls/Card/Themes/CardTabsContentTheme.axaml @@ -6,7 +6,41 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/AtomUI.Controls/Card/Themes/CardTheme.axaml b/src/AtomUI.Controls/Card/Themes/CardTheme.axaml index c11dcfa1b..8f0a9d3a8 100644 --- a/src/AtomUI.Controls/Card/Themes/CardTheme.axaml +++ b/src/AtomUI.Controls/Card/Themes/CardTheme.axaml @@ -118,6 +118,12 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + - +