feat: improve demo.

This commit is contained in:
rabbitism
2024-01-05 00:08:15 +08:00
parent 86b71a3c82
commit c6bc631e0d
5 changed files with 161 additions and 100 deletions

View File

@@ -14,45 +14,48 @@
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<ResourceDictionary> <ResourceDictionary>
<selectors:TimelineIconTemplateSelector x:Key="IconSelector"> <selectors:TimelineIconTemplateSelector x:Key="IconSelector" >
<Ellipse <SolidColorBrush x:Key="Default" Color="{DynamicResource SemiGray6Color}"></SolidColorBrush>
x:Key="Default" <SolidColorBrush x:Key="Ongoing" Color="{DynamicResource SemiBlue6Color}"></SolidColorBrush>
Width="12" <SolidColorBrush x:Key="Success" Color="{DynamicResource SemiGreen6Color}"></SolidColorBrush>
Height="12" <SolidColorBrush x:Key="Warning" Color="{DynamicResource SemiOrange6Color}"></SolidColorBrush>
Fill="{DynamicResource SemiGray6}" /> <SolidColorBrush x:Key="Error" Color="{DynamicResource SemiRed6Color}"></SolidColorBrush>
<Ellipse
x:Key="Ongoing"
Width="12"
Height="12"
Fill="{DynamicResource SemiBlue6}" />
<Ellipse
x:Key="Success"
Width="12"
Height="12"
Fill="{DynamicResource SemiGreen6}" />
<Ellipse
x:Key="Warning"
Width="12"
Height="12"
Fill="{DynamicResource SemiOrange6}" />
<Ellipse
x:Key="Error"
Width="12"
Height="12"
Fill="{DynamicResource SemiRed6}" />
</selectors:TimelineIconTemplateSelector> </selectors:TimelineIconTemplateSelector>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<StackPanel> <StackPanel>
<u:Timeline <u:Timeline
Mode="Alternate"
HorizontalAlignment="Left" HorizontalAlignment="Left"
DescriptionMemberBinding="{ReflectionBinding Description}" ContentMemberBinding="{ReflectionBinding Description}"
HeaderMemberBinding="{ReflectionBinding Header}" HeaderMemberBinding="{ReflectionBinding Header}"
IconMemberBinding="{ReflectionBinding ItemType}" IconMemberBinding="{ReflectionBinding ItemType}"
IconTemplate="{StaticResource IconSelector}" IconTemplate="{StaticResource IconSelector}"
ItemsSource="{Binding Items}" ItemsSource="{Binding Items}"
TimeMemberBinding="{ReflectionBinding Time}" /> TimeMemberBinding="{ReflectionBinding Time}" >
<u:Timeline HorizontalAlignment="Left">
</u:Timeline>
<u:Timeline
Mode="Left"
HorizontalAlignment="Left"
ContentMemberBinding="{ReflectionBinding Description}"
HeaderMemberBinding="{ReflectionBinding Header}"
IconMemberBinding="{ReflectionBinding ItemType}"
IconTemplate="{StaticResource IconSelector}"
ItemsSource="{Binding Items}"
TimeMemberBinding="{ReflectionBinding Time}" >
</u:Timeline>
<u:Timeline
Mode="Right"
HorizontalAlignment="Left"
ContentMemberBinding="{ReflectionBinding Description}"
HeaderMemberBinding="{ReflectionBinding Header}"
IconMemberBinding="{ReflectionBinding ItemType}"
IconTemplate="{StaticResource IconSelector}"
ItemsSource="{Binding Items}"
TimeMemberBinding="{ReflectionBinding Time}" >
</u:Timeline>
<u:Timeline HorizontalAlignment="Left" Mode="Alternate">
<u:TimelineItem <u:TimelineItem
Content="Step 1" Content="Step 1"
Header="第一步" Header="第一步"

View File

@@ -17,7 +17,11 @@ public class TimelineIconTemplateSelector: ResourceDictionary, IDataTemplate
if (ContainsKey(s)) if (ContainsKey(s))
{ {
object? o = this[s]; object? o = this[s];
if (o is Control c) return c; if (o is SolidColorBrush c)
{
var ellipse = new Ellipse() { Width = 12, Height = 12, Fill = c };
return ellipse;
}
} }
} }
return null; return null;

View File

@@ -32,13 +32,14 @@
WarningBrush="{DynamicResource WarningTimelineIconForeground}" /> WarningBrush="{DynamicResource WarningTimelineIconForeground}" />
<ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem"> <ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem">
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top"></Setter> <Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="u:TimelineItem.Template"> <Setter Property="u:TimelineItem.Template">
<ControlTemplate TargetType="u:TimelineItem"> <ControlTemplate TargetType="u:TimelineItem">
<Grid Name="PART_RootGrid" <Grid
RowDefinitions="Auto, Auto, Auto" Name="PART_RootGrid"
ColumnDefinitions="Auto, Auto, Auto"> ColumnDefinitions="Auto, Auto, Auto"
RowDefinitions="Auto, Auto, Auto">
<!-- Icon and Axis --> <!-- Icon and Axis -->
<Grid <Grid
Name="PART_IconAxisRoot" Name="PART_IconAxisRoot"
@@ -63,36 +64,38 @@
Fill="{DynamicResource TimelineLineBrush}" /> Fill="{DynamicResource TimelineLineBrush}" />
</Grid> </Grid>
<ContentPresenter <ContentPresenter
Name="PART_Header"
Grid.Row="0" Grid.Row="0"
Grid.Column="2" Grid.Column="2"
Name="PART_Header" Margin="8,4"
Margin="8 4" VerticalAlignment="Top"
Content="{TemplateBinding Header}" Content="{TemplateBinding Header}"
Foreground="{DynamicResource SemiGrey9}" ContentTemplate="{TemplateBinding HeaderTemplate}"
FontSize="14" FontSize="14"
ContentTemplate="{TemplateBinding HeaderTemplate}" /> Foreground="{DynamicResource SemiGrey9}" />
<ContentPresenter <ContentPresenter
Name="PART_Content"
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
Name="PART_Content" Margin="8,2"
Margin="8 2" VerticalAlignment="Top"
TextElement.Foreground="Gray"
TextElement.FontSize="12"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" /> ContentTemplate="{TemplateBinding ContentTemplate}"
TextElement.FontSize="12"
TextElement.Foreground="Gray" />
<TextBlock <TextBlock
Name="PART_Time"
Grid.Row="0" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
Name="PART_Time" Margin="8,2"
Margin="8 2 8 16" VerticalAlignment="Top"
Foreground="Gray"
FontSize="12" FontSize="12"
TextWrapping="Wrap" Foreground="Gray"
> TextWrapping="Wrap">
<TextBlock.Text> <TextBlock.Text>
<MultiBinding Converter="{StaticResource FormatConverter}"> <MultiBinding Converter="{StaticResource FormatConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Time"></Binding> <Binding Path="Time" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="TimeFormat"></Binding> <Binding Path="TimeFormat" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
</TextBlock> </TextBlock>
@@ -117,62 +120,65 @@
</Style> </Style>
<Style Selector="^:all-left"> <Style Selector="^:all-left">
<Style Selector="^ /template/ ContentPresenter#PART_Header"> <Style Selector="^ /template/ ContentPresenter#PART_Header">
<Setter Property="Grid.Row" Value="0"></Setter> <Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0"></Setter> <Setter Property="Grid.Column" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Right"></Setter> <Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="HorizontalAlignment" Value="Right"></Setter> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
<Style Selector="^ /template/ ContentPresenter#PART_Content"> <Style Selector="^ /template/ ContentPresenter#PART_Content">
<Setter Property="Grid.Row" Value="1"></Setter> <Setter Property="Grid.Row" Value="1" />
<Setter Property="Grid.Column" Value="0"></Setter> <Setter Property="Grid.Column" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Right"></Setter> <Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="HorizontalAlignment" Value="Right"></Setter> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
<Style Selector="^ /template/ TextBlock#PART_Time"> <Style Selector="^ /template/ TextBlock#PART_Time">
<Setter Property="Grid.Row" Value="2"></Setter> <Setter Property="Grid.Row" Value="2" />
<Setter Property="Grid.Column" Value="0"></Setter> <Setter Property="Grid.Column" Value="0" />
<Setter Property="TextAlignment" Value="Right"></Setter> <Setter Property="TextAlignment" Value="Right" />
<Setter Property="HorizontalAlignment" Value="Right"></Setter> <Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Margin" Value="8 2 8 12"></Setter>
</Style> </Style>
</Style> </Style>
<Style Selector="^:all-right"> <Style Selector="^:all-right">
<Style Selector="^ /template/ ContentPresenter#PART_Header"> <Style Selector="^ /template/ ContentPresenter#PART_Header">
<Setter Property="Grid.Row" Value="0"></Setter> <Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="2"></Setter> <Setter Property="Grid.Column" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter> <Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
</Style> </Style>
<Style Selector="^ /template/ ContentPresenter#PART_Content"> <Style Selector="^ /template/ ContentPresenter#PART_Content">
<Setter Property="Grid.Row" Value="1"></Setter> <Setter Property="Grid.Row" Value="1" />
<Setter Property="Grid.Column" Value="2"></Setter> <Setter Property="Grid.Column" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter> <Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
</Style> </Style>
<Style Selector="^ /template/ TextBlock#PART_Time"> <Style Selector="^ /template/ TextBlock#PART_Time">
<Setter Property="Grid.Row" Value="2"></Setter> <Setter Property="Grid.Row" Value="2" />
<Setter Property="Grid.Column" Value="2"></Setter> <Setter Property="Grid.Column" Value="2" />
<Setter Property="TextAlignment" Value="Left"></Setter> <Setter Property="TextAlignment" Value="Left" />
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Margin" Value="8 2 8 12"></Setter>
</Style> </Style>
</Style> </Style>
<Style Selector="^:separate"> <Style Selector="^:separate">
<Style Selector="^ /template/ ContentPresenter#PART_Header"> <Style Selector="^ /template/ ContentPresenter#PART_Header">
<Setter Property="Grid.Row" Value="0"></Setter> <Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="2"></Setter> <Setter Property="Grid.Column" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter> <Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
</Style> </Style>
<Style Selector="^ /template/ ContentPresenter#PART_Content"> <Style Selector="^ /template/ ContentPresenter#PART_Content">
<Setter Property="Grid.Row" Value="1"></Setter> <Setter Property="Grid.Row" Value="1" />
<Setter Property="Grid.Column" Value="2"></Setter> <Setter Property="Grid.Column" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter> <Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="HorizontalAlignment" Value="Left"></Setter> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Margin" Value="8 2 8 12"></Setter>
</Style> </Style>
<Style Selector="^ /template/ TextBlock#PART_Time"> <Style Selector="^ /template/ TextBlock#PART_Time">
<Setter Property="Grid.Row" Value="0"></Setter> <Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0"></Setter> <Setter Property="Grid.Column" Value="0" />
<Setter Property="TextAlignment" Value="Right"></Setter> <Setter Property="TextAlignment" Value="Right" />
<Setter Property="HorizontalAlignment" Value="Right"></Setter> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
</Style> </Style>
</ControlTheme> </ControlTheme>

View File

@@ -37,15 +37,15 @@ public class Timeline: ItemsControl
set => SetValue(HeaderMemberBindingProperty, value); set => SetValue(HeaderMemberBindingProperty, value);
} }
public static readonly StyledProperty<IBinding?> DescriptionMemberBindingProperty = AvaloniaProperty.Register<Timeline, IBinding?>( public static readonly StyledProperty<IBinding?> ContentMemberBindingProperty = AvaloniaProperty.Register<Timeline, IBinding?>(
nameof(DescriptionMemberBinding)); nameof(ContentMemberBinding));
[AssignBinding] [AssignBinding]
[InheritDataTypeFromItems(nameof(ItemsSource))] [InheritDataTypeFromItems(nameof(ItemsSource))]
public IBinding? DescriptionMemberBinding public IBinding? ContentMemberBinding
{ {
get => GetValue(DescriptionMemberBindingProperty); get => GetValue(ContentMemberBindingProperty);
set => SetValue(DescriptionMemberBindingProperty, value); set => SetValue(ContentMemberBindingProperty, value);
} }
@@ -110,6 +110,7 @@ public class Timeline: ItemsControl
if (this.ItemsPanelRoot is TimelinePanel panel) if (this.ItemsPanelRoot is TimelinePanel panel)
{ {
panel.Mode = e.NewValue.Value; panel.Mode = e.NewValue.Value;
SetItemMode();
} }
} }
@@ -133,7 +134,7 @@ public class Timeline: ItemsControl
bool start = index == 0; bool start = index == 0;
bool end = index == ItemCount - 1; bool end = index == ItemCount - 1;
t.SetEnd(start, end); t.SetEnd(start, end);
if (IconMemberBinding != null) if (IconMemberBinding is not null)
{ {
t.Bind(TimelineItem.IconProperty, IconMemberBinding); t.Bind(TimelineItem.IconProperty, IconMemberBinding);
} }
@@ -141,9 +142,9 @@ public class Timeline: ItemsControl
{ {
t.Bind(HeaderedContentControl.HeaderProperty, HeaderMemberBinding); t.Bind(HeaderedContentControl.HeaderProperty, HeaderMemberBinding);
} }
if (DescriptionMemberBinding != null) if (ContentMemberBinding != null)
{ {
t.Bind(ContentControl.ContentProperty, DescriptionMemberBinding); t.Bind(ContentControl.ContentProperty, ContentMemberBinding);
} }
if (TimeMemberBinding != null) if (TimeMemberBinding != null)
{ {
@@ -161,6 +162,58 @@ public class Timeline: ItemsControl
{ {
var panel = this.ItemsPanelRoot as TimelinePanel; var panel = this.ItemsPanelRoot as TimelinePanel;
panel.Mode = this.Mode; panel.Mode = this.Mode;
SetItemMode();
return base.ArrangeOverride(finalSize); return base.ArrangeOverride(finalSize);
} }
private void SetItemMode()
{
if (ItemsPanelRoot is TimelinePanel panel)
{
var items = panel.Children.OfType<TimelineItem>();
if (Mode == TimelineDisplayMode.Left)
{
foreach (var item in items)
{
SetIfUnset(item, TimelineItem.ModeProperty, TimelineItemDisplayMode.Left);
}
}
else if (Mode == TimelineDisplayMode.Right)
{
foreach (var item in items)
{
SetIfUnset(item, TimelineItem.ModeProperty, TimelineItemDisplayMode.Right);
}
}
else if (Mode == TimelineDisplayMode.Center)
{
foreach (var item in items)
{
SetIfUnset(item, TimelineItem.ModeProperty, TimelineItemDisplayMode.Separate);
}
}
else if (Mode == TimelineDisplayMode.Alternate)
{
bool left = false;
foreach (var item in items)
{
if (left)
{
SetIfUnset(item, TimelineItem.ModeProperty, TimelineItemDisplayMode.Left);
}
else
{
SetIfUnset(item, TimelineItem.ModeProperty, TimelineItemDisplayMode.Right);
}
left = !left;
}
}
}
}
private void SetIfUnset<T>(AvaloniaObject target, StyledProperty<T> property, T value)
{
if (!target.IsSet(property))
target.SetCurrentValue(property, value);
}
} }

View File

@@ -74,9 +74,4 @@ public class TimelinePanel: Panel
//return base.ArrangeOverride(finalSize); //return base.ArrangeOverride(finalSize);
return new Size(left + mid + right, height); return new Size(left + mid + right, height);
} }
public override void ApplyTemplate()
{
base.ApplyTemplate();
}
} }