Fix a bunch of templating issues
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc1" />
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Toolkit.Foundation\Toolkit.Foundation.csproj" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0-preview.5.24306.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0-preview.6.24327.7" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc1" />
|
||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.1.0-rc1" />
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc2" />
|
||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.1.0-rc2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Toolkit.Foundation\Toolkit.Foundation.csproj" />
|
||||
|
||||
@@ -8,106 +8,138 @@ namespace Toolkit.UI.Controls.Avalonia;
|
||||
public class ContentBadge :
|
||||
ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<string?> BadgePathProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, string?>(nameof(BadgePath));
|
||||
|
||||
public static readonly StyledProperty<double> BadgeSizeProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, double>(nameof(BadgeSize), 14);
|
||||
public static readonly StyledProperty<string> BadgePathProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, string>(nameof(BadgePath));
|
||||
|
||||
public static readonly StyledProperty<ContentBadgePlacement> BadgePlacementProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, ContentBadgePlacement>(nameof(BadgePlacement), ContentBadgePlacement.BottomRight);
|
||||
|
||||
public static readonly StyledProperty<double> BadgeSizeProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, double>(nameof(BadgeSize), 14);
|
||||
|
||||
public static readonly StyledProperty<bool> IsBadgeVisibleProperty =
|
||||
AvaloniaProperty.Register<ContentBadge, bool>(nameof(IsBadgeVisible), true);
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == BadgePathProperty ||
|
||||
change.Property == BadgeSizeProperty ||
|
||||
change.Property == IsBadgeVisibleProperty)
|
||||
{
|
||||
UpdateBadge();
|
||||
}
|
||||
}
|
||||
|
||||
private ContentControl? badgeContent;
|
||||
|
||||
public string BadgePath
|
||||
{
|
||||
get => GetValue(BadgePathProperty);
|
||||
set => SetValue(BadgePathProperty, value);
|
||||
}
|
||||
|
||||
public ContentBadgePlacement BadgePlacement
|
||||
{
|
||||
get => GetValue(BadgePlacementProperty);
|
||||
set => SetValue(BadgePlacementProperty, value);
|
||||
}
|
||||
|
||||
public string? BadgePath
|
||||
{
|
||||
get => GetValue(BadgePathProperty);
|
||||
set => SetValue(BadgePathProperty, value);
|
||||
}
|
||||
|
||||
public double BadgeSize
|
||||
{
|
||||
get => GetValue(BadgeSizeProperty);
|
||||
set => SetValue(BadgeSizeProperty, value);
|
||||
}
|
||||
|
||||
public void UpdateClip()
|
||||
public bool IsBadgeVisible
|
||||
{
|
||||
if (Content is Control content &&
|
||||
badgeContent is not null &&
|
||||
BadgePath is { Length: > 0 } &&
|
||||
Geometry.Parse(BadgePath) is Geometry geometry)
|
||||
get => GetValue(IsBadgeVisibleProperty);
|
||||
set => SetValue(IsBadgeVisibleProperty, value);
|
||||
}
|
||||
|
||||
public void UpdateBadge()
|
||||
{
|
||||
if (Content is Control content && badgeContent is not null)
|
||||
{
|
||||
double backgroundWidth = DesiredSize.Width;
|
||||
double backgroundHeight = DesiredSize.Height;
|
||||
|
||||
double scaleX = BadgeSize / geometry.Bounds.Width;
|
||||
double scaleY = BadgeSize / geometry.Bounds.Height;
|
||||
|
||||
double adjustedStrokeWidth = Math.Min(scaleX, scaleY) * 8;
|
||||
|
||||
Geometry knockoutGeometry = geometry.GetWidenedGeometry(new Pen(new SolidColorBrush(Colors.Transparent), adjustedStrokeWidth));
|
||||
|
||||
TransformGroup transformGroup = new();
|
||||
transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
double scaledWidth = knockoutGeometry.Bounds.Width * scaleX;
|
||||
double scaledHeight = knockoutGeometry.Bounds.Height * scaleY;
|
||||
|
||||
double offsetX = 0;
|
||||
double offsetY = 0;
|
||||
|
||||
switch (BadgePlacement)
|
||||
if (IsBadgeVisible &&
|
||||
BadgePath is { Length: > 0 } &&
|
||||
Geometry.Parse(BadgePath) is Geometry geometry)
|
||||
{
|
||||
case ContentBadgePlacement.TopLeft:
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.TopRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomLeft:
|
||||
offsetX = 0;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
double backgroundWidth = DesiredSize.Width;
|
||||
double backgroundHeight = DesiredSize.Height;
|
||||
|
||||
double badgeWidth = geometry.Bounds.Width;
|
||||
double badgeHeight = geometry.Bounds.Height;
|
||||
double scale = BadgeSize / Math.Max(badgeWidth, badgeHeight);
|
||||
|
||||
double scaleX = scale;
|
||||
double scaleY = scale;
|
||||
|
||||
double adjustedStrokeWidth = Math.Min(scaleX, scaleY) * 8;
|
||||
|
||||
Geometry knockoutGeometry = geometry.GetWidenedGeometry(new Pen(new SolidColorBrush(Colors.Transparent), adjustedStrokeWidth));
|
||||
|
||||
TransformGroup transformGroup = new();
|
||||
transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
double scaledWidth = knockoutGeometry.Bounds.Width * scaleX;
|
||||
double scaledHeight = knockoutGeometry.Bounds.Height * scaleY;
|
||||
|
||||
double offsetX = 0;
|
||||
double offsetY = 0;
|
||||
|
||||
switch (BadgePlacement)
|
||||
{
|
||||
case ContentBadgePlacement.TopLeft:
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.TopRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = 0;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomLeft:
|
||||
offsetX = 0;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
case ContentBadgePlacement.BottomRight:
|
||||
offsetX = backgroundWidth - scaledWidth;
|
||||
offsetY = backgroundHeight - scaledHeight;
|
||||
break;
|
||||
}
|
||||
|
||||
transformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
knockoutGeometry.Transform = transformGroup;
|
||||
|
||||
CombinedGeometry combinedGeometry = new()
|
||||
{
|
||||
GeometryCombineMode = GeometryCombineMode.Exclude,
|
||||
Geometry1 = new RectangleGeometry { Rect = new Rect(0, 0, backgroundWidth, backgroundHeight) },
|
||||
Geometry2 = knockoutGeometry
|
||||
};
|
||||
|
||||
content.Clip = combinedGeometry;
|
||||
|
||||
Geometry overlayGeometry = geometry.Clone();
|
||||
|
||||
TransformGroup overlayTransformGroup = new();
|
||||
overlayTransformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
overlayTransformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
overlayGeometry.Transform = overlayTransformGroup;
|
||||
|
||||
badgeContent.Content = new Path
|
||||
{
|
||||
Data = overlayGeometry,
|
||||
Fill = Foreground
|
||||
};
|
||||
}
|
||||
|
||||
transformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
knockoutGeometry.Transform = transformGroup;
|
||||
|
||||
CombinedGeometry combinedGeometry = new()
|
||||
else
|
||||
{
|
||||
GeometryCombineMode = GeometryCombineMode.Exclude,
|
||||
Geometry1 = new RectangleGeometry { Rect = new Rect(0, 0, backgroundWidth, backgroundHeight) },
|
||||
Geometry2 = knockoutGeometry
|
||||
};
|
||||
|
||||
content.Clip = combinedGeometry;
|
||||
|
||||
Geometry overlayGeometry = geometry.Clone();
|
||||
|
||||
TransformGroup overlayTransformGroup = new();
|
||||
overlayTransformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
|
||||
|
||||
overlayTransformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
|
||||
overlayGeometry.Transform = overlayTransformGroup;
|
||||
|
||||
badgeContent.Content = new Path
|
||||
{
|
||||
Data = overlayGeometry,
|
||||
Fill = Foreground
|
||||
};
|
||||
badgeContent.Content = null;
|
||||
content.Clip = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +152,7 @@ public class ContentBadge :
|
||||
protected override void OnSizeChanged(SizeChangedEventArgs args)
|
||||
{
|
||||
base.OnSizeChanged(args);
|
||||
UpdateClip();
|
||||
UpdateBadge();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,44 @@
|
||||
<x:Double x:Key="OverflowItemSpacing">6</x:Double>
|
||||
<x:Double x:Key="OverflowItemSize">40</x:Double>
|
||||
<CornerRadius x:Key="OverflowItemCornerRadius">40</CornerRadius>
|
||||
<ControlTheme x:Key="OverflowItemStyle" TargetType="ListBoxItem">
|
||||
<ControlTheme x:Key="{x:Type OverflowList}" TargetType="OverflowList">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ListBoxForeground}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ListBoxBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ListBoxBorder}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource ListBoxBorderThemeThickness}" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="ScrollViewer.IsScrollChainingEnabled" Value="True" />
|
||||
<Setter Property="ScrollViewer.IsScrollInertiaEnabled" Value="True" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
Name="border"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ScrollViewer
|
||||
Name="PART_ScrollViewer"
|
||||
AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BringIntoViewOnFocusChange="{TemplateBinding (ScrollViewer.BringIntoViewOnFocusChange)}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
|
||||
HorizontalSnapPointsType="{TemplateBinding (ScrollViewer.HorizontalSnapPointsType)}"
|
||||
IsDeferredScrollingEnabled="{TemplateBinding (ScrollViewer.IsDeferredScrollingEnabled)}"
|
||||
IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}"
|
||||
IsScrollInertiaEnabled="{TemplateBinding (ScrollViewer.IsScrollInertiaEnabled)}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"
|
||||
VerticalSnapPointsType="{TemplateBinding (ScrollViewer.VerticalSnapPointsType)}">
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
<ControlTheme x:Key="{x:Type controls:OverflowItem}" TargetType="controls:OverflowItem">
|
||||
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="Background" Value="{DynamicResource ListViewItemBackground}" />
|
||||
@@ -34,21 +71,28 @@
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid>
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
<Border
|
||||
Name="SelectionIndicator"
|
||||
BorderBrush="{DynamicResource AccentFillColorDefaultBrush}"
|
||||
BorderThickness="3"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsVisible="False"
|
||||
UseLayoutRounding="False" />
|
||||
</Grid>
|
||||
<controls:ContentBadge
|
||||
BadgePath="{TemplateBinding BadgePath}"
|
||||
BadgePlacement="{TemplateBinding BadgePlacement}"
|
||||
BadgeSize="{TemplateBinding BadgeSize}"
|
||||
Foreground="Red"
|
||||
IsBadgeVisible="{TemplateBinding IsBadgeVisible}">
|
||||
<Grid>
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
/>
|
||||
<Border
|
||||
Name="SelectionIndicator"
|
||||
BorderBrush="{DynamicResource AccentFillColorDefaultBrush}"
|
||||
BorderThickness="3"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsVisible="False"
|
||||
UseLayoutRounding="False" />
|
||||
</Grid>
|
||||
</controls:ContentBadge>
|
||||
</Border>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
@@ -116,18 +160,17 @@
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<StackPanel Margin="{TemplateBinding Margin}">
|
||||
<ListBox
|
||||
<controls:OverflowList
|
||||
x:Name="PrimaryListBox"
|
||||
Grid.Column="0"
|
||||
ItemContainerTheme="{StaticResource OverflowItemStyle}"
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}"
|
||||
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.PrimarySelection, Mode=TwoWay}">
|
||||
<ListBox.ItemsPanel>
|
||||
<controls:OverflowList.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="{StaticResource OverflowItemSpacing}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
</ListBox>
|
||||
</controls:OverflowList.ItemsPanel>
|
||||
</controls:OverflowList>
|
||||
<Grid
|
||||
x:Name="Spacer"
|
||||
Grid.Column="1"
|
||||
@@ -153,17 +196,16 @@
|
||||
</Viewbox>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<ListBox
|
||||
<controls:OverflowList
|
||||
x:Name="SecondaryListBox"
|
||||
ItemContainerTheme="{StaticResource OverflowItemStyle}"
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}"
|
||||
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.SecondarySelection, Mode=TwoWay}">
|
||||
<ListBox.ItemsPanel>
|
||||
<controls:OverflowList.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="{StaticResource OverflowItemSpacing}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
</ListBox>
|
||||
</controls:OverflowList.ItemsPanel>
|
||||
</controls:OverflowList>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
@@ -29,13 +29,14 @@ public class Overflow :
|
||||
private static readonly StyledProperty<OverflowTemplateSettings> TemplateSettingsProperty =
|
||||
AvaloniaProperty.Register<Overflow, OverflowTemplateSettings>(nameof(TemplateSettings));
|
||||
|
||||
|
||||
private readonly ObservableCollection<object> primaryCollection = [];
|
||||
|
||||
private readonly ObservableCollection<object> secondaryCollection = [];
|
||||
|
||||
private ListBox? primaryListBox;
|
||||
private OverflowList? primaryListBox;
|
||||
|
||||
private ListBox? secondaryListBox;
|
||||
private OverflowList? secondaryListBox;
|
||||
|
||||
public Overflow()
|
||||
{
|
||||
@@ -59,7 +60,6 @@ public class Overflow :
|
||||
get => GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
[InheritDataTypeFromItems(nameof(ItemsSource))]
|
||||
public IDataTemplate? ItemTemplate
|
||||
{
|
||||
@@ -83,10 +83,10 @@ public class Overflow :
|
||||
{
|
||||
base.OnApplyTemplate(args);
|
||||
|
||||
primaryListBox = args.NameScope.Get<ListBox>("PrimaryListBox");
|
||||
primaryListBox = args.NameScope.Get<OverflowList>("PrimaryListBox");
|
||||
primaryListBox?.SetValue(ItemsControl.ItemsSourceProperty, primaryCollection);
|
||||
|
||||
secondaryListBox = args.NameScope.Get<ListBox>("SecondaryListBox");
|
||||
secondaryListBox = args.NameScope.Get<OverflowList>("SecondaryListBox");
|
||||
secondaryListBox?.SetValue(ItemsControl.ItemsSourceProperty, secondaryCollection);
|
||||
|
||||
InitializeCollections();
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
public class OverflowItem :
|
||||
ListBoxItem
|
||||
{
|
||||
public static readonly StyledProperty<double> BadgeSizeProperty =
|
||||
AvaloniaProperty.Register<OverflowItem, double>(nameof(BadgeSize), 14);
|
||||
|
||||
public static readonly StyledProperty<bool> IsBadgeVisibleProperty =
|
||||
AvaloniaProperty.Register<OverflowItem, bool>(nameof(IsBadgeVisible), true);
|
||||
|
||||
public static readonly StyledProperty<string> BadgePathProperty =
|
||||
AvaloniaProperty.Register<OverflowItem, string>(nameof(BadgePath));
|
||||
|
||||
public static readonly StyledProperty<ContentBadgePlacement> BadgePlacementProperty =
|
||||
AvaloniaProperty.Register<OverflowItem, ContentBadgePlacement>(nameof(BadgePlacement), ContentBadgePlacement.BottomRight);
|
||||
|
||||
public string BadgePath
|
||||
{
|
||||
get => GetValue(BadgePathProperty);
|
||||
set => SetValue(BadgePathProperty, value);
|
||||
}
|
||||
|
||||
public ContentBadgePlacement BadgePlacement
|
||||
{
|
||||
get => GetValue(BadgePlacementProperty);
|
||||
set => SetValue(BadgePlacementProperty, value);
|
||||
}
|
||||
|
||||
public double BadgeSize
|
||||
{
|
||||
get => GetValue(BadgeSizeProperty);
|
||||
set => SetValue(BadgeSizeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsBadgeVisible
|
||||
{
|
||||
get => GetValue(IsBadgeVisibleProperty);
|
||||
set => SetValue(IsBadgeVisibleProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
public class OverflowList :
|
||||
ListBox
|
||||
{
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
if (recycleKey is IDataTemplate itemContainerTemplate)
|
||||
{
|
||||
if (itemContainerTemplate.Build(item) is OverflowItem container)
|
||||
{
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
return new OverflowItem();
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
if (item is OverflowItem)
|
||||
{
|
||||
recycleKey = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.FindDataTemplate(item, ItemTemplate) is IDataTemplate itemContainerTemplate)
|
||||
{
|
||||
recycleKey = itemContainerTemplate;
|
||||
return true;
|
||||
}
|
||||
|
||||
recycleKey = DefaultRecycleKey;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
public class TemplateListBox :
|
||||
ListBox
|
||||
{
|
||||
protected override Type StyleKeyOverride =>
|
||||
typeof(ListBox);
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
if (recycleKey is IDataTemplate itemContainerTemplate)
|
||||
{
|
||||
if (itemContainerTemplate.Build(item) is ListBoxItem container)
|
||||
{
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
return new ListBoxItem();
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
if (item is ListBoxItem)
|
||||
{
|
||||
recycleKey = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.FindDataTemplate(item, ItemTemplate) is IDataTemplate itemContainerTemplate)
|
||||
{
|
||||
recycleKey = itemContainerTemplate;
|
||||
return true;
|
||||
}
|
||||
|
||||
recycleKey = DefaultRecycleKey;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<AvaloniaResource Include="Fonts\FluentSystemIcons-Resizable.ttf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc1" />
|
||||
<PackageReference Include="Avalonia" Version="11.1.0-rc2" />
|
||||
<PackageReference Include="Avalonia.Labs.Controls" Version="11.0.10.1" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.1.0-preview6" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user