Browse Source

experiment for CSD template

exp/drawn-decorations-template
Nikita Tsukanov 4 weeks ago
parent
commit
ea0bb316ff
  1. 161
      samples/Sandbox/DrawnDecorationsPresenter.cs
  2. 44
      samples/Sandbox/MainWindow.axaml
  3. 1
      src/Avalonia.Base/Avalonia.Base.csproj
  4. 1
      src/Avalonia.Controls/Avalonia.Controls.csproj
  5. 2
      src/Avalonia.Controls/Primitives/TemplatedControl.cs

161
samples/Sandbox/DrawnDecorationsPresenter.cs

@ -0,0 +1,161 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Metadata;
using Avalonia.Styling;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Sandbox.Controls")]
namespace Sandbox.Controls;
public class DrawnDecorationsPresenter : Control
{
class Wrapper : Control
{
public Control? Inner
{
get=>field;
set
{
if (field == value)
return;
if (field != null)
VisualChildren.Remove(field);
field = value;
if (field != null)
VisualChildren.Add(field);
}
}
}
private WindowDrawnDecorations _decorations = new WindowDrawnDecorations();
private Grid _grid = new Grid();
private Wrapper _overlay = new Wrapper(), _underlay = new Wrapper();
public DrawnDecorationsPresenter()
{
LogicalChildren.Add(_decorations);
((ISetLogicalParent)_decorations).SetParent(this);
VisualChildren.Add(_grid);
_grid.Children.Add(_underlay);
_grid.Children.Add(_overlay);
}
public override void ApplyTemplate()
{
_decorations.ApplyTemplate();
_overlay.Inner = _decorations.Content?.Overlay;
_underlay.Inner = _decorations.Content?.Underlay;
base.ApplyTemplate();
}
}
[ControlTemplateScope]
public class WindowDrawnDecorationsTemplate : ITemplate
{
[Content]
[TemplateContent(TemplateResultType = typeof(WindowDrawnDecorationsContent))]
public object? Content { get; set; }
public TemplateResult<WindowDrawnDecorationsContent> Build() =>
TemplateContent.Load<WindowDrawnDecorationsContent>(Content) ?? throw new InvalidOperationException();
object? ITemplate.Build() => Build();
}
public class WindowDrawnDecorationsContent : StyledElement
{
public Control? Overlay
{
get => field;
set => HandleLogicalChild(ref field, value);
}
public Control? Underlay
{
get => field;
set => HandleLogicalChild(ref field, value);
}
void HandleLogicalChild(ref Control? field, Control? value)
{
if (field == value)
return;
if (field != null)
{
LogicalChildren.Remove(field);
((ISetLogicalParent)field).SetParent(null);
}
field = value;
if (field != null)
{
LogicalChildren.Add(field);
((ISetLogicalParent)field).SetParent(this);
}
}
}
[PseudoClasses(":test")]
public class WindowDrawnDecorations : StyledElement
{
public WindowDrawnDecorations()
{
PseudoClasses.Add(":test");
}
public static readonly StyledProperty<WindowDrawnDecorationsTemplate> TemplateProperty = AvaloniaProperty.Register<WindowDrawnDecorations, WindowDrawnDecorationsTemplate>(
"Template");
public WindowDrawnDecorationsTemplate Template
{
get => GetValue(TemplateProperty);
set => SetValue(TemplateProperty, value);
}
public static readonly StyledProperty<double> TitleBarHeightProperty = AvaloniaProperty.Register<WindowDrawnDecorations, double>(
"TitleBarHeight");
public double TitleBarHeight
{
get => GetValue(TitleBarHeightProperty);
set => SetValue(TitleBarHeightProperty, value);
}
public WindowDrawnDecorationsContent? Content { get; private set; }
private WindowDrawnDecorationsTemplate? _appliedTemplate;
public void ApplyTemplate()
{
if (Template == _appliedTemplate)
return;
if (Content != null)
{
LogicalChildren.Remove(Content);
((ISetLogicalParent)Content).SetParent(null);
Content = null;
}
var res = Template.Build();
Content = res.Result;
if (Content != null)
{
TemplatedControl.ApplyTemplatedParent(Content, this);
LogicalChildren.Add(Content);
((ISetLogicalParent)Content).SetParent(this);
}
}
}
class TestTest : Border
{
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
}
}

44
samples/Sandbox/MainWindow.axaml

@ -1,4 +1,44 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class="Sandbox.MainWindow">
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:sandbox="clr-namespace:Sandbox"
x:Class="Sandbox.MainWindow">
<Window.Resources>
<ResourceDictionary>
<ControlTheme x:Key="{x:Type WindowDrawnDecorations}" TargetType="WindowDrawnDecorations">
<Setter Property="TitleBarHeight" Value="32"/>
<Setter Property="Template">
<WindowDrawnDecorationsTemplate>
<WindowDrawnDecorationsContent>
<WindowDrawnDecorationsContent.Overlay>
<StackPanel x:Name="PART_TitleBar" VerticalAlignment="Top" Orientation="Horizontal" Height="{TemplateBinding TitleBarHeight}">
<TextBlock Foreground="Green" FontSize="20">TITLEBAR</TextBlock>
<TextBlock Foreground="Green" Text="{TemplateBinding TitleBarHeight}"/>
</StackPanel>
</WindowDrawnDecorationsContent.Overlay>
<WindowDrawnDecorationsContent.Underlay>
<Border Background="Azure" BorderThickness="1" BorderBrush="Gray"/>
</WindowDrawnDecorationsContent.Underlay>
</WindowDrawnDecorationsContent>
</WindowDrawnDecorationsTemplate>
</Setter>
<Style Selector="^ /template/ StackPanel">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="^ /template/ TestTest">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="^:test /template/ StackPanel#PART_TitleBar">
<Setter Property="Background" Value="DarkBlue"/>
</Style>
</ControlTheme>
</ResourceDictionary>
</Window.Resources>
<DrawnDecorationsPresenter/>
</Window>

1
src/Avalonia.Base/Avalonia.Base.csproj

@ -25,6 +25,7 @@
</ItemGroup>
<ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Sandbox, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Base.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Desktop, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Benchmarks, PublicKey=$(AvaloniaPublicKey)" />

1
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -11,6 +11,7 @@
<Import Project="..\..\build\DevAnalyzers.props" />
<ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Sandbox, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Controls.ItemsRepeater, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Skia.RenderTests, PublicKey=$(AvaloniaPublicKey)" />

2
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -422,7 +422,7 @@ namespace Avalonia.Controls.Primitives
/// </summary>
/// <param name="control">The control.</param>
/// <param name="templatedParent">The templated parent to apply.</param>
internal static void ApplyTemplatedParent(StyledElement control, AvaloniaObject? templatedParent)
public static void ApplyTemplatedParent(StyledElement control, AvaloniaObject? templatedParent)
{
control.TemplatedParent = templatedParent;

Loading…
Cancel
Save