committed by
GitHub
6 changed files with 584 additions and 32 deletions
@ -0,0 +1,190 @@ |
|||||
|
using System.ComponentModel; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Layout; |
||||
|
using Avalonia.VisualTree; |
||||
|
|
||||
|
namespace Avalonia.Diagnostics.ViewModels |
||||
|
{ |
||||
|
internal class ControlLayoutViewModel : ViewModelBase |
||||
|
{ |
||||
|
private readonly IVisual _control; |
||||
|
private Thickness _marginThickness; |
||||
|
private Thickness _borderThickness; |
||||
|
private Thickness _paddingThickness; |
||||
|
private double _width; |
||||
|
private double _height; |
||||
|
private string _widthConstraint; |
||||
|
private string _heightConstraint; |
||||
|
private bool _updatingFromControl; |
||||
|
|
||||
|
public Thickness MarginThickness |
||||
|
{ |
||||
|
get => _marginThickness; |
||||
|
set => RaiseAndSetIfChanged(ref _marginThickness, value); |
||||
|
} |
||||
|
|
||||
|
public Thickness BorderThickness |
||||
|
{ |
||||
|
get => _borderThickness; |
||||
|
set => RaiseAndSetIfChanged(ref _borderThickness, value); |
||||
|
} |
||||
|
|
||||
|
public Thickness PaddingThickness |
||||
|
{ |
||||
|
get => _paddingThickness; |
||||
|
set => RaiseAndSetIfChanged(ref _paddingThickness, value); |
||||
|
} |
||||
|
|
||||
|
public double Width |
||||
|
{ |
||||
|
get => _width; |
||||
|
private set => RaiseAndSetIfChanged(ref _width, value); |
||||
|
} |
||||
|
|
||||
|
public double Height |
||||
|
{ |
||||
|
get => _height; |
||||
|
private set => RaiseAndSetIfChanged(ref _height, value); |
||||
|
} |
||||
|
|
||||
|
public string WidthConstraint |
||||
|
{ |
||||
|
get => _widthConstraint; |
||||
|
private set => RaiseAndSetIfChanged(ref _widthConstraint, value); |
||||
|
} |
||||
|
|
||||
|
public string HeightConstraint |
||||
|
{ |
||||
|
get => _heightConstraint; |
||||
|
private set => RaiseAndSetIfChanged(ref _heightConstraint, value); |
||||
|
} |
||||
|
|
||||
|
public bool HasPadding { get; } |
||||
|
|
||||
|
public bool HasBorder { get; } |
||||
|
|
||||
|
public ControlLayoutViewModel(IVisual control) |
||||
|
{ |
||||
|
_control = control; |
||||
|
|
||||
|
HasPadding = AvaloniaPropertyRegistry.Instance.IsRegistered(control, Decorator.PaddingProperty); |
||||
|
HasBorder = AvaloniaPropertyRegistry.Instance.IsRegistered(control, Border.BorderThicknessProperty); |
||||
|
|
||||
|
if (control is AvaloniaObject ao) |
||||
|
{ |
||||
|
MarginThickness = ao.GetValue(Layoutable.MarginProperty); |
||||
|
|
||||
|
if (HasPadding) |
||||
|
{ |
||||
|
PaddingThickness = ao.GetValue(Decorator.PaddingProperty); |
||||
|
} |
||||
|
|
||||
|
if (HasBorder) |
||||
|
{ |
||||
|
BorderThickness = ao.GetValue(Border.BorderThicknessProperty); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
UpdateSize(); |
||||
|
UpdateSizeConstraints(); |
||||
|
} |
||||
|
|
||||
|
private void UpdateSizeConstraints() |
||||
|
{ |
||||
|
if (_control is IAvaloniaObject ao) |
||||
|
{ |
||||
|
string CreateConstraintInfo(StyledProperty<double> minProperty, StyledProperty<double> maxProperty) |
||||
|
{ |
||||
|
if (ao.IsSet(minProperty) || ao.IsSet(maxProperty)) |
||||
|
{ |
||||
|
var minValue = ao.GetValue(minProperty); |
||||
|
var maxValue = ao.GetValue(maxProperty); |
||||
|
|
||||
|
return $"{minValue} < size < {maxValue}"; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
WidthConstraint = CreateConstraintInfo(Layoutable.MinWidthProperty, Layoutable.MaxWidthProperty); |
||||
|
HeightConstraint = CreateConstraintInfo(Layoutable.MinHeightProperty, Layoutable.MaxHeightProperty); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override void OnPropertyChanged(PropertyChangedEventArgs e) |
||||
|
{ |
||||
|
base.OnPropertyChanged(e); |
||||
|
|
||||
|
if (_updatingFromControl) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (_control is AvaloniaObject ao) |
||||
|
{ |
||||
|
if (e.PropertyName == nameof(MarginThickness)) |
||||
|
{ |
||||
|
ao.SetValue(Layoutable.MarginProperty, MarginThickness); |
||||
|
} |
||||
|
else if (HasPadding && e.PropertyName == nameof(PaddingThickness)) |
||||
|
{ |
||||
|
ao.SetValue(Decorator.PaddingProperty, PaddingThickness); |
||||
|
} |
||||
|
else if (HasBorder && e.PropertyName == nameof(BorderThickness)) |
||||
|
{ |
||||
|
ao.SetValue(Border.BorderThicknessProperty, BorderThickness); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void ControlPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_updatingFromControl = true; |
||||
|
|
||||
|
if (e.Property == Visual.BoundsProperty) |
||||
|
{ |
||||
|
UpdateSize(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (_control is IAvaloniaObject ao) |
||||
|
{ |
||||
|
if (e.Property == Layoutable.MarginProperty) |
||||
|
{ |
||||
|
MarginThickness = ao.GetValue(Layoutable.MarginProperty); |
||||
|
} |
||||
|
else if (e.Property == Decorator.PaddingProperty) |
||||
|
{ |
||||
|
PaddingThickness = ao.GetValue(Decorator.PaddingProperty); |
||||
|
} |
||||
|
else if (e.Property == Border.BorderThicknessProperty) |
||||
|
{ |
||||
|
BorderThickness = ao.GetValue(Border.BorderThicknessProperty); |
||||
|
} |
||||
|
else if (e.Property == Layoutable.MinWidthProperty || |
||||
|
e.Property == Layoutable.MaxWidthProperty || |
||||
|
e.Property == Layoutable.MinHeightProperty || |
||||
|
e.Property == Layoutable.MaxHeightProperty) |
||||
|
{ |
||||
|
UpdateSizeConstraints(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_updatingFromControl = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void UpdateSize() |
||||
|
{ |
||||
|
var size = _control.Bounds; |
||||
|
|
||||
|
Width = size.Width; |
||||
|
Height = size.Height; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,38 +1,155 @@ |
|||||
<UserControl xmlns="https://github.com/avaloniaui" |
<UserControl xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:conv="clr-namespace:Avalonia.Diagnostics.Converters" |
xmlns:conv="clr-namespace:Avalonia.Diagnostics.Converters" |
||||
|
xmlns:local="clr-namespace:Avalonia.Diagnostics.Views" |
||||
x:Class="Avalonia.Diagnostics.Views.ControlDetailsView"> |
x:Class="Avalonia.Diagnostics.Views.ControlDetailsView"> |
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,*"> |
|
||||
|
|
||||
<TextBox Grid.Row="0" Grid.Column="0" |
|
||||
BorderThickness="0" |
|
||||
Text="{Binding TreePage.PropertyFilter}" |
|
||||
Watermark="Filter properties" /> |
|
||||
|
|
||||
<CheckBox Grid.Row="0" |
|
||||
Grid.Column="1" |
|
||||
Content="Regex" |
|
||||
IsChecked="{Binding TreePage.UseRegexFilter}"/> |
|
||||
|
|
||||
<DataGrid Items="{Binding PropertiesView}" |
|
||||
Grid.Row="1" Grid.ColumnSpan="2" |
|
||||
BorderThickness="0" |
|
||||
RowBackground="Transparent" |
|
||||
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}" |
|
||||
CanUserResizeColumns="true"> |
|
||||
<DataGrid.Columns> |
|
||||
<DataGridTextColumn Header="Property" Binding="{Binding Name}" IsReadOnly="True" /> |
|
||||
<DataGridTextColumn Header="Value" Binding="{Binding Value}" /> |
|
||||
<DataGridTextColumn Header="Type" Binding="{Binding Type}" /> |
|
||||
<DataGridTextColumn Header="Priority" Binding="{Binding Priority}" IsReadOnly="True" /> |
|
||||
</DataGrid.Columns> |
|
||||
|
|
||||
<DataGrid.Styles> |
|
||||
<Style Selector="DataGridRow TextBox"> |
|
||||
<Setter Property="SelectionBrush" Value="LightBlue"/> |
|
||||
</Style> |
|
||||
</DataGrid.Styles> |
|
||||
</DataGrid> |
|
||||
|
|
||||
|
<UserControl.Resources> |
||||
|
<SolidColorBrush x:Key="ThicknessBorderBrush" Color="#666666" /> |
||||
|
<SolidColorBrush x:Key="SizeGuidelineBrush" Color="#333333" /> |
||||
|
<SolidColorBrush x:Key="MarginBackgroundBrush" Color="#D78965" /> |
||||
|
<SolidColorBrush x:Key="BorderBackgroundBrush" Color="#E3C381" /> |
||||
|
<SolidColorBrush x:Key="PaddingBackgroundBrush" Color="#B8C47F" /> |
||||
|
<SolidColorBrush x:Key="SizeBackgroundBrush" Color="#88B2BD" /> |
||||
|
</UserControl.Resources> |
||||
|
|
||||
|
<UserControl.Styles> |
||||
|
<Style Selector="local|ThicknessEditor"> |
||||
|
<Setter Property="HorizontalContentAlignment" Value="Center" /> |
||||
|
<Setter Property="VerticalContentAlignment" Value="Center" /> |
||||
|
<Setter Property="BorderThickness" Value="1" /> |
||||
|
<Setter Property="BorderBrush" Value="{StaticResource ThicknessBorderBrush}" /> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<Border |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness}"> |
||||
|
<Grid RowDefinitions="Auto,*,Auto" ColumnDefinitions="Auto,*,Auto"> |
||||
|
<Grid.Styles> |
||||
|
<Style Selector="TextBox.thickness-edit"> |
||||
|
<Setter Property="Background" Value="Transparent" /> |
||||
|
<Setter Property="BorderThickness" Value="0" /> |
||||
|
<Setter Property="Margin" Value="2" /> |
||||
|
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
||||
|
<Setter Property="VerticalAlignment" Value="Stretch" /> |
||||
|
<Setter Property="HorizontalContentAlignment" Value="Center" /> |
||||
|
<Setter Property="VerticalContentAlignment" Value="Center" /> |
||||
|
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)" Value="Disabled" /> |
||||
|
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Disabled" /> |
||||
|
<Setter Property="IsVisible" Value="{Binding $parent[local:ThicknessEditor].IsPresent}" /> |
||||
|
</Style> |
||||
|
</Grid.Styles> |
||||
|
<TextBlock IsVisible="{TemplateBinding IsPresent}" Margin="4,0,0,0" Text="{TemplateBinding Header}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" /> |
||||
|
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding Left, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" /> |
||||
|
<TextBox x:Name="Right" Grid.Row="0" Grid.Column="1" Text="{Binding Top, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" /> |
||||
|
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Right, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" /> |
||||
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Bottom, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" /> |
||||
|
<ContentPresenter Grid.Row="1" Grid.Column="1" |
||||
|
Name="PART_ContentPresenter" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Content="{TemplateBinding Content}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" /> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
|
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
<Style Selector="local|ThicknessEditor[IsPresent=False]"> |
||||
|
<Setter Property="BorderThickness" Value="0" /> |
||||
|
</Style> |
||||
|
</UserControl.Styles> |
||||
|
|
||||
|
<Grid ColumnDefinitions="*,Auto,280"> |
||||
|
|
||||
|
<Grid Grid.Column="0" ColumnDefinitions="*,Auto,Auto,Auto" RowDefinitions="Auto,*"> |
||||
|
|
||||
|
<TextBox Grid.Row="0" |
||||
|
Grid.Column="0" |
||||
|
BorderThickness="0" |
||||
|
Text="{Binding TreePage.PropertyFilter}" |
||||
|
Watermark="Filter properties" /> |
||||
|
|
||||
|
<CheckBox Grid.Row="0" |
||||
|
Grid.Column="1" |
||||
|
Margin="0,0,4,0" |
||||
|
Content="Regex" |
||||
|
IsChecked="{Binding TreePage.UseRegexFilter}" /> |
||||
|
|
||||
|
<DataGrid Items="{Binding PropertiesView}" |
||||
|
Grid.Row="1" |
||||
|
Grid.Column="0" |
||||
|
Grid.ColumnSpan="2" |
||||
|
BorderThickness="0" |
||||
|
RowBackground="Transparent" |
||||
|
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}" |
||||
|
CanUserResizeColumns="true"> |
||||
|
<DataGrid.Columns> |
||||
|
<DataGridTextColumn Header="Property" Binding="{Binding Name}" IsReadOnly="True" /> |
||||
|
<DataGridTextColumn Header="Value" Binding="{Binding Value}" /> |
||||
|
<DataGridTextColumn Header="Type" Binding="{Binding Type}" /> |
||||
|
<DataGridTextColumn Header="Priority" Binding="{Binding Priority}" IsReadOnly="True" /> |
||||
|
</DataGrid.Columns> |
||||
|
|
||||
|
<DataGrid.Styles> |
||||
|
<Style Selector="DataGridRow TextBox"> |
||||
|
<Setter Property="SelectionBrush" Value="LightBlue" /> |
||||
|
</Style> |
||||
|
</DataGrid.Styles> |
||||
|
</DataGrid> |
||||
|
|
||||
|
</Grid> |
||||
|
|
||||
|
<GridSplitter Grid.Column="1" /> |
||||
|
|
||||
|
<Grid Grid.Column="2" RowDefinitions="Auto,*" > |
||||
|
<TextBlock Grid.Row="0" Text="Layout Visualizer" Margin="4" /> |
||||
|
|
||||
|
<Grid Grid.Row="1" x:Name="LayoutRoot" Margin="8,0,8,8" RowDefinitions="Auto,Auto" ColumnDefinitions="Auto,Auto"> |
||||
|
|
||||
|
<Border x:Name="VerticalSize" Grid.Row="0" Grid.Column="1" > |
||||
|
<TextBlock VerticalAlignment="Center" FontWeight="Bold" |
||||
|
TextDecorations="{Binding Layout.HeightConstraint, Converter={x:Static local:Converters.HasConstraintConverter}}" |
||||
|
Text="{Binding Layout.Height}" |
||||
|
ToolTip.Tip="{Binding Layout.HeightConstraint}" /> |
||||
|
</Border> |
||||
|
|
||||
|
<Border x:Name="HorizontalSize" Grid.Row="1" Grid.Column="0" > |
||||
|
<TextBlock HorizontalAlignment="Center" FontWeight="Bold" |
||||
|
TextDecorations="{Binding Layout.WidthConstraint, Converter={x:Static local:Converters.HasConstraintConverter}}" |
||||
|
Text="{Binding Layout.Width}" |
||||
|
ToolTip.Tip="{Binding Layout.WidthConstraint}" /> |
||||
|
</Border> |
||||
|
|
||||
|
<local:ThicknessEditor Grid.Row="0" Grid.Column="0" Header="margin" VerticalAlignment="Top" HorizontalAlignment="Center" Background="{StaticResource MarginBackgroundBrush}" Thickness="{Binding Layout.MarginThickness}"> |
||||
|
<local:ThicknessEditor x:Name="BorderArea" Header="border" Background="{StaticResource BorderBackgroundBrush}" Thickness="{Binding Layout.BorderThickness}" IsPresent="{Binding Layout.HasBorder}"> |
||||
|
<local:ThicknessEditor x:Name="PaddingArea" Header="padding" Background="{StaticResource PaddingBackgroundBrush}" Thickness="{Binding Layout.PaddingThickness}" IsPresent="{Binding Layout.HasPadding}"> |
||||
|
<Border x:Name="ContentArea" BorderThickness="1" BorderBrush="{StaticResource ThicknessBorderBrush}" MinWidth="100" MinHeight="16" Background="{StaticResource SizeBackgroundBrush}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> |
||||
|
<TextBlock Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Text="content" /> |
||||
|
</Border> |
||||
|
</local:ThicknessEditor> |
||||
|
</local:ThicknessEditor> |
||||
|
</local:ThicknessEditor> |
||||
|
|
||||
|
<Canvas Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2"> |
||||
|
<Canvas.Styles> |
||||
|
<Style Selector="Rectangle"> |
||||
|
<Setter Property="StrokeDashArray" Value="1,3" /> |
||||
|
<Setter Property="Stroke" Value="{StaticResource SizeGuidelineBrush}" /> |
||||
|
<Setter Property="StrokeThickness" Value="1" /> |
||||
|
</Style> |
||||
|
</Canvas.Styles> |
||||
|
<Rectangle x:Name="HorizontalSizeBegin" /> |
||||
|
<Rectangle x:Name="HorizontalSizeEnd" /> |
||||
|
<Rectangle x:Name="VerticalSizeBegin" /> |
||||
|
<Rectangle x:Name="VerticalSizeEnd" /> |
||||
|
</Canvas> |
||||
|
</Grid> |
||||
|
|
||||
|
</Grid> |
||||
</Grid> |
</Grid> |
||||
|
|
||||
</UserControl> |
</UserControl> |
||||
|
|||||
@ -0,0 +1,130 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Data; |
||||
|
using Avalonia.Data.Converters; |
||||
|
using Avalonia.Media; |
||||
|
|
||||
|
namespace Avalonia.Diagnostics.Views |
||||
|
{ |
||||
|
internal static class Converters |
||||
|
{ |
||||
|
public static IValueConverter HasConstraintConverter = |
||||
|
new FuncValueConverter<object, TextDecorationCollection>(ConvertToDecoration); |
||||
|
|
||||
|
private static TextDecorationCollection ConvertToDecoration(object arg) |
||||
|
{ |
||||
|
return arg != null ? TextDecorations.Underline : null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal class ThicknessEditor : ContentControl |
||||
|
{ |
||||
|
public static readonly DirectProperty<ThicknessEditor, Thickness> ThicknessProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, Thickness>(nameof(Thickness), o => o.Thickness, |
||||
|
(o, v) => o.Thickness = v, defaultBindingMode: BindingMode.TwoWay); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, string> HeaderProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, string>(nameof(Header), o => o.Header, |
||||
|
(o, v) => o.Header = v); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, bool> IsPresentProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, bool>(nameof(Header), o => o.IsPresent, |
||||
|
(o, v) => o.IsPresent = v); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, double> LeftProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, double>(nameof(Left), o => o.Left, (o, v) => o.Left = v); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, double> TopProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, double>(nameof(Top), o => o.Top, (o, v) => o.Top = v); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, double> RightProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, double>(nameof(Right), o => o.Right, |
||||
|
(o, v) => o.Right = v); |
||||
|
|
||||
|
public static readonly DirectProperty<ThicknessEditor, double> BottomProperty = |
||||
|
AvaloniaProperty.RegisterDirect<ThicknessEditor, double>(nameof(Bottom), o => o.Bottom, |
||||
|
(o, v) => o.Bottom = v); |
||||
|
|
||||
|
|
||||
|
private Thickness _thickness; |
||||
|
private string _header; |
||||
|
private bool _isPresent = true; |
||||
|
private double _left; |
||||
|
private double _top; |
||||
|
private double _right; |
||||
|
private double _bottom; |
||||
|
|
||||
|
private bool _isUpdatingThickness; |
||||
|
|
||||
|
public Thickness Thickness |
||||
|
{ |
||||
|
get => _thickness; |
||||
|
set => SetAndRaise(ThicknessProperty, ref _thickness, value); |
||||
|
} |
||||
|
|
||||
|
public string Header |
||||
|
{ |
||||
|
get => _header; |
||||
|
set => SetAndRaise(HeaderProperty, ref _header, value); |
||||
|
} |
||||
|
|
||||
|
public bool IsPresent |
||||
|
{ |
||||
|
get => _isPresent; |
||||
|
set => SetAndRaise(IsPresentProperty, ref _isPresent, value); |
||||
|
} |
||||
|
|
||||
|
public double Left |
||||
|
{ |
||||
|
get => _left; |
||||
|
set => SetAndRaise(LeftProperty, ref _left, value); |
||||
|
} |
||||
|
|
||||
|
public double Top |
||||
|
{ |
||||
|
get => _top; |
||||
|
set => SetAndRaise(TopProperty, ref _top, value); |
||||
|
} |
||||
|
|
||||
|
public double Right |
||||
|
{ |
||||
|
get => _right; |
||||
|
set => SetAndRaise(RightProperty, ref _right, value); |
||||
|
} |
||||
|
|
||||
|
public double Bottom |
||||
|
{ |
||||
|
get => _bottom; |
||||
|
set => SetAndRaise(BottomProperty, ref _bottom, value); |
||||
|
} |
||||
|
|
||||
|
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) |
||||
|
{ |
||||
|
base.OnPropertyChanged(change); |
||||
|
|
||||
|
if (change.Property == ThicknessProperty) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_isUpdatingThickness = true; |
||||
|
|
||||
|
var value = change.NewValue.GetValueOrDefault<Thickness>(); |
||||
|
|
||||
|
Left = value.Left; |
||||
|
Top = value.Top; |
||||
|
Right = value.Right; |
||||
|
Bottom = value.Bottom; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_isUpdatingThickness = false; |
||||
|
} |
||||
|
} |
||||
|
else if (!_isUpdatingThickness && |
||||
|
(change.Property == LeftProperty || change.Property == TopProperty || |
||||
|
change.Property == RightProperty || change.Property == BottomProperty)) |
||||
|
{ |
||||
|
Thickness = new Thickness(Left, Top, Right, Bottom); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue