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" |
<Window xmlns="https://github.com/avaloniaui" |
||||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
||||
x:Class="Sandbox.MainWindow"> |
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> |
</Window> |
||||
|
|||||
Loading…
Reference in new issue