5 changed files with 206 additions and 3 deletions
@ -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); |
|||
} |
|||
} |
|||
@ -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> |
|||
|
|||
Loading…
Reference in new issue