feat: add demo page, prepare collection changed behavior.

This commit is contained in:
rabbitism
2023-03-23 12:52:02 +08:00
parent 615ba9ce0a
commit 0f139264cc
11 changed files with 253 additions and 40 deletions

View File

@@ -1,6 +1,11 @@
using System.Collections.Specialized;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.ComTypes;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
namespace Ursa.Controls;
@@ -17,33 +22,33 @@ public class Timeline: ItemsControl
set => SetValue(ItemDescriptionTemplateProperty, value);
}
protected override bool IsItemItsOwnContainerOverride(Control item)
public Timeline()
{
return item is TimelineItem;
ItemsView.CollectionChanged+=ItemsViewOnCollectionChanged;
}
protected override Control CreateContainerForItemOverride()
private void ItemsViewOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
return new TimelineItem();
RefreshTimelineItems();
}
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.PrepareContainerForItemOverride(container, item, index);
if (container is TimelineItem c )
base.OnPropertyChanged(change);
RefreshTimelineItems();
}
private void RefreshTimelineItems()
{
for (int i = 0; i < this.LogicalChildren.Count; i++)
{
if (item is ITimelineItemData data)
if (this.LogicalChildren[i] is TimelineItem t)
{
c[TimelineItem.TimeProperty] = data;
c[ContentControl.ContentProperty] = data.Content;
c[TimelineItem.DescriptionProperty] = data.Description;
if(ItemTemplate is {}) c[ContentControl.ContentTemplateProperty] = this.ItemTemplate;
if(ItemDescriptionTemplate is {}) c[TimelineItem.DescriptionTemplateProperty] = this.ItemDescriptionTemplate;
t.SetPosition(i == 0, i == this.LogicalChildren.Count - 1);
}
else
else if (this.LogicalChildren[i] is ContentPresenter { Child: TimelineItem t2 })
{
c.Content = item;
if (ItemTemplate is { }) c[ContentControl.ContentTemplateProperty] = this.ItemTemplate;
t2.SetPosition(i == 0, i == this.LogicalChildren.Count - 1);
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Globalization;
using Avalonia;
using Avalonia.Data.Converters;
namespace Ursa.Controls;
public class TimelineFormatConverter: IMultiValueConverter
{
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
{
if (values.Count> 1 && values[0] is DateTime date && values[1] is string s)
{
return date.ToString(s, culture);
}
return AvaloniaProperty.UnsetValue;
}
}

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
@@ -12,7 +13,7 @@ public class TimelineItem: ContentControl
{
public const string PC_First = ":first";
public const string PC_Last = ":last";
public static readonly StyledProperty<IBrush> IconForegroundProperty =
AvaloniaProperty.Register<TimelineItem, IBrush>(nameof(IconForeground));
@@ -40,7 +41,7 @@ public class TimelineItem: ContentControl
}
public static readonly StyledProperty<string?> TimeFormatProperty = AvaloniaProperty.Register<TimelineItem, string?>(
nameof(TimeFormat));
nameof(TimeFormat), defaultValue:CultureInfo.CurrentUICulture.DateTimeFormat.SortableDateTimePattern);
public string? TimeFormat
{
@@ -56,4 +57,10 @@ public class TimelineItem: ContentControl
get => GetValue(DescriptionTemplateProperty);
set => SetValue(DescriptionTemplateProperty, value);
}
internal void SetPosition(bool isFirst, bool isLast)
{
PseudoClasses.Set(PC_First, isFirst);
PseudoClasses.Set(PC_Last, isLast);
}
}

View File

@@ -1,9 +0,0 @@
namespace Ursa.Controls;
public interface ITimelineItemData
{
public DateTime Time { get; set; }
public object Content { get; set; }
public object Description { get; set; }
public TimelineItemType ItemType { get; set; }
}

View File

@@ -1,12 +0,0 @@
namespace Ursa.Controls;
/// <summary>
/// Describe how TimelineItem components should be placed around the line.
/// </summary>
public enum TimelinePlacement
{
Left,
Right,
Center,
Alternate,
}