feat: add more properties.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AvaloniaVersion>11.0.0</AvaloniaVersion>
|
<AvaloniaVersion>11.0.9</AvaloniaVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,27 +1,58 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl
|
||||||
|
x:Class="Ursa.Demo.Pages.FormDemo"
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:common="clr-namespace:Ursa.Common;assembly=Ursa"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
|
||||||
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels;assembly=Ursa.Demo"
|
|
||||||
xmlns:u="https://irihi.tech/ursa"
|
xmlns:u="https://irihi.tech/ursa"
|
||||||
x:DataType="vm:FormDemoViewModel"
|
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels;assembly=Ursa.Demo"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
d:DesignWidth="800"
|
||||||
x:CompileBindings="True"
|
x:CompileBindings="True"
|
||||||
x:Class="Ursa.Demo.Pages.FormDemo">
|
x:DataType="vm:FormDemoViewModel"
|
||||||
|
mc:Ignorable="d">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<u:Form DataContext="{Binding Model}" LabelWidth="Auto">
|
<StackPanel>
|
||||||
|
<u:EnumSelector
|
||||||
|
Name="position"
|
||||||
|
EnumType="common:Position"
|
||||||
|
Value="{x:Static common:Position.Top}" />
|
||||||
|
<u:EnumSelector
|
||||||
|
Name="alignment"
|
||||||
|
EnumType="HorizontalAlignment"
|
||||||
|
Value="{x:Static HorizontalAlignment.Left}" />
|
||||||
|
</StackPanel>
|
||||||
|
<u:Form
|
||||||
|
DataContext="{Binding Model}"
|
||||||
|
LabelAlignment="{Binding #alignment.Value}"
|
||||||
|
LabelPosition="{Binding #position.Value}"
|
||||||
|
LabelWidth="*">
|
||||||
<u:FormGroup Header="Information">
|
<u:FormGroup Header="Information">
|
||||||
<TextBox u:Form.Label="Name" Text="{Binding Name}" Width="300"/>
|
<TextBox
|
||||||
<TextBox u:Form.Label="Email" Text="{Binding Email}" Width="300"/>
|
Width="300"
|
||||||
|
u:FormItem.IsRequired="True"
|
||||||
|
u:FormItem.Label="Name"
|
||||||
|
Text="{Binding Name}" />
|
||||||
|
<TextBox
|
||||||
|
Width="300"
|
||||||
|
u:FormItem.Label="Email"
|
||||||
|
Text="{Binding Email}" />
|
||||||
</u:FormGroup>
|
</u:FormGroup>
|
||||||
<u:FormItem>
|
<u:FormItem Label="Please select a Date">
|
||||||
<CalendarDatePicker u:Form.Label="Date" SelectedDate="{Binding Date}" />
|
<Calendar SelectedDate="{Binding Date}" />
|
||||||
|
</u:FormItem>
|
||||||
|
<u:FormItem Label="Click to Submit">
|
||||||
|
<Button Content="With Label" />
|
||||||
|
</u:FormItem>
|
||||||
|
<u:FormItem NoLabel="True">
|
||||||
|
<Button HorizontalAlignment="Left" Content="No Label" />
|
||||||
</u:FormItem>
|
</u:FormItem>
|
||||||
</u:Form>
|
</u:Form>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock Text="{Binding Model.Name}"></TextBlock>
|
<TextBlock Text="{Binding Model.Name}" />
|
||||||
<TextBlock Text="{Binding Model.Email}"></TextBlock>
|
<TextBlock Text="{Binding Model.Email}" />
|
||||||
<TextBlock Text="{Binding Model.Date}"></TextBlock>
|
<TextBlock Text="{Binding Model.Date}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
||||||
<PackageReference Include="Semi.Avalonia" Version="11.0.0" />
|
<PackageReference Include="Semi.Avalonia" Version="11.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
<ResourceDictionary
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<!-- Add Resources Here -->
|
<!-- Add Resources Here -->
|
||||||
<ControlTheme x:Key="{x:Type u:Form}" TargetType="u:Form">
|
<ControlTheme x:Key="{x:Type u:Form}" TargetType="u:Form">
|
||||||
|
<Setter Property="Grid.IsSharedSizeScope" Value="False" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:Form">
|
<ControlTemplate TargetType="u:Form">
|
||||||
<DataValidationErrors>
|
<DataValidationErrors>
|
||||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}"></ItemsPresenter>
|
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||||
</DataValidationErrors>
|
</DataValidationErrors>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Style Selector="^:fixed-width">
|
||||||
|
<Setter Property="Grid.IsSharedSizeScope" Value="True" />
|
||||||
|
</Style>
|
||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:FormGroup}" TargetType="u:FormGroup">
|
<ControlTheme x:Key="{x:Type u:FormGroup}" TargetType="u:FormGroup">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:FormGroup">
|
<ControlTemplate TargetType="u:FormGroup">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<ContentPresenter Content="{TemplateBinding Header}"/>
|
<ContentPresenter Content="{TemplateBinding Header}" FontWeight="Bold" />
|
||||||
|
<Rectangle
|
||||||
|
Height="1"
|
||||||
|
Margin="0,8"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Fill="LightGray" />
|
||||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
@@ -24,13 +35,63 @@
|
|||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:FormItem}" TargetType="u:FormItem">
|
<ControlTheme x:Key="{x:Type u:FormItem}" TargetType="u:FormItem">
|
||||||
|
<Setter Property="Margin" Value="0 8" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:FormItem">
|
<ControlTemplate TargetType="u:FormItem">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel>
|
||||||
<TextBlock Text="{TemplateBinding Label}" />
|
<StackPanel
|
||||||
|
Name="PART_LabelPanel"
|
||||||
|
Margin="0,0,0,4"
|
||||||
|
HorizontalAlignment="{TemplateBinding LabelAlignment}"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<ContentPresenter Content="{TemplateBinding Label}" FontWeight="Bold" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{DynamicResource SemiRed6}"
|
||||||
|
IsVisible="{TemplateBinding IsRequired}"
|
||||||
|
Text="*" />
|
||||||
|
</StackPanel>
|
||||||
<ContentPresenter Content="{TemplateBinding Content}" />
|
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
<Style Selector="^:not(:no-label):horizontal">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate TargetType="u:FormItem">
|
||||||
|
<Grid RowDefinitions="*, *">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Width="{TemplateBinding LabelWidth}">
|
||||||
|
<StackPanel
|
||||||
|
Name="PART_LabelPanel"
|
||||||
|
Margin="8,8,8,0"
|
||||||
|
HorizontalAlignment="{TemplateBinding LabelAlignment}"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<ContentPresenter Content="{TemplateBinding Label}" FontWeight="Bold" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{DynamicResource SemiRed6}"
|
||||||
|
IsVisible="{TemplateBinding IsRequired}"
|
||||||
|
Text="*" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<ContentPresenter
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Content="{TemplateBinding Content}" />
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:no-label">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate TargetType="u:FormItem">
|
||||||
|
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -1,59 +1,65 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
|
using Avalonia.Layout;
|
||||||
using Ursa.Common;
|
using Ursa.Common;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
[PseudoClasses(PC_FixedWidth)]
|
||||||
public class Form: ItemsControl
|
public class Form: ItemsControl
|
||||||
{
|
{
|
||||||
#region Attached Properties
|
public const string PC_FixedWidth = ":fixed-width";
|
||||||
|
|
||||||
public static readonly AttachedProperty<object?> LabelProperty =
|
public static readonly StyledProperty<GridLength> LabelWidthProperty = AvaloniaProperty.Register<Form, GridLength>(
|
||||||
AvaloniaProperty.RegisterAttached<Form, Control, object?>("Label");
|
nameof(LabelWidth));
|
||||||
public static void SetLabel(Control obj, object? value) => obj.SetValue(LabelProperty, value);
|
|
||||||
public static object? GetLabel(Control obj) => obj.GetValue(LabelProperty);
|
|
||||||
|
|
||||||
|
|
||||||
public static readonly AttachedProperty<bool> IsRequiredProperty =
|
|
||||||
AvaloniaProperty.RegisterAttached<Form, Control, bool>("IsRequired");
|
|
||||||
public static void SetIsRequired(Control obj, bool value) => obj.SetValue(IsRequiredProperty, value);
|
|
||||||
public static bool GetIsRequired(Control obj) => obj.GetValue(IsRequiredProperty);
|
|
||||||
|
|
||||||
public static readonly AttachedProperty<GridLength> LabelWidthProperty =
|
|
||||||
AvaloniaProperty.RegisterAttached<Form, Control, GridLength>("LabelWidth");
|
|
||||||
|
|
||||||
public static void SetLabelWidth(Control obj, GridLength value) => obj.SetValue(LabelWidthProperty, value);
|
|
||||||
public static GridLength GetLabelWidth(Control obj) => obj.GetValue(LabelWidthProperty);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Behavior:
|
||||||
|
/// <para>Fixed Width: all labels are with fixed length. </para>
|
||||||
|
/// <para>Star: all labels are aligned by max length. </para>
|
||||||
|
/// <para>Auto: labels are not aligned. </para>
|
||||||
|
/// </summary>
|
||||||
|
public GridLength LabelWidth
|
||||||
|
{
|
||||||
|
get => GetValue(LabelWidthProperty);
|
||||||
|
set => SetValue(LabelWidthProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Position> LabelPositionProperty = AvaloniaProperty.Register<Form, Position>(
|
public static readonly StyledProperty<Position> LabelPositionProperty = AvaloniaProperty.Register<Form, Position>(
|
||||||
nameof(LabelPosition));
|
nameof(LabelPosition), defaultValue: Position.Top);
|
||||||
/// <summary>
|
|
||||||
/// Only Left and Top work.
|
|
||||||
/// </summary>
|
|
||||||
public Position LabelPosition
|
public Position LabelPosition
|
||||||
{
|
{
|
||||||
get => GetValue(LabelPositionProperty);
|
get => GetValue(LabelPositionProperty);
|
||||||
set => SetValue(LabelPositionProperty, value);
|
set => SetValue(LabelPositionProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Position> LabelAlignmentProperty = AvaloniaProperty.Register<Form, Position>(
|
public static readonly StyledProperty<HorizontalAlignment> LabelAlignmentProperty = AvaloniaProperty.Register<Form, HorizontalAlignment>(
|
||||||
nameof(LabelAlignment));
|
nameof(LabelAlignment), defaultValue: HorizontalAlignment.Left);
|
||||||
/// <summary>
|
|
||||||
/// Only Left and Right work.
|
public HorizontalAlignment LabelAlignment
|
||||||
/// </summary>
|
|
||||||
public Position LabelAlignment
|
|
||||||
{
|
{
|
||||||
get => GetValue(LabelAlignmentProperty);
|
get => GetValue(LabelAlignmentProperty);
|
||||||
set => SetValue(LabelAlignmentProperty, value);
|
set => SetValue(LabelAlignmentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Form()
|
||||||
|
{
|
||||||
|
LabelWidthProperty.Changed.AddClassHandler<Form, GridLength>((x, args) => x.LabelWidthChanged(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LabelWidthChanged(AvaloniaPropertyChangedEventArgs<GridLength> args)
|
||||||
|
{
|
||||||
|
var newValue = args.NewValue.Value;
|
||||||
|
bool isFixed = newValue.IsStar || newValue.IsAbsolute;
|
||||||
|
PseudoClasses.Set(PC_FixedWidth, isFixed);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||||
{
|
{
|
||||||
recycleKey = null;
|
recycleKey = null;
|
||||||
return item is FormItem or FormGroup;
|
return item is not FormItem && item is not FormGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||||
@@ -62,27 +68,8 @@ public class Form: ItemsControl
|
|||||||
return new FormItem()
|
return new FormItem()
|
||||||
{
|
{
|
||||||
Content = control,
|
Content = control,
|
||||||
[!LabelProperty] = control.GetObservable(Form.LabelProperty).ToBinding(),
|
[!FormItem.LabelProperty] = control[!FormItem.LabelProperty],
|
||||||
[!IsRequiredProperty] = control.GetObservable(Form.IsRequiredProperty).ToBinding(),
|
[!FormItem.IsRequiredProperty] = control[!FormItem.IsRequiredProperty],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
|
||||||
{
|
|
||||||
base.PrepareContainerForItemOverride(container, item, index);
|
|
||||||
if (container is FormGroup group)
|
|
||||||
{
|
|
||||||
if (!group.IsSet(FormGroup.LabelWidthProperty))
|
|
||||||
{
|
|
||||||
group[!LabelWidthProperty] = this.GetObservable(LabelWidthProperty).ToBinding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (container is FormItem formItem)
|
|
||||||
{
|
|
||||||
if(!formItem.IsSet(FormItem.LabelWidthProperty))
|
|
||||||
{
|
|
||||||
formItem[!LabelWidthProperty] = this.GetObservable(LabelWidthProperty).ToBinding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,13 +6,6 @@ namespace Ursa.Controls;
|
|||||||
|
|
||||||
public class FormGroup: HeaderedItemsControl
|
public class FormGroup: HeaderedItemsControl
|
||||||
{
|
{
|
||||||
public static readonly StyledProperty<GridLength> LabelWidthProperty = Form.LabelWidthProperty.AddOwner<FormGroup>();
|
|
||||||
|
|
||||||
public GridLength LabelWidth
|
|
||||||
{
|
|
||||||
get => GetValue(LabelWidthProperty);
|
|
||||||
set => SetValue(LabelWidthProperty, value);
|
|
||||||
}
|
|
||||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||||
{
|
{
|
||||||
recycleKey = null;
|
recycleKey = null;
|
||||||
@@ -25,17 +18,9 @@ public class FormGroup: HeaderedItemsControl
|
|||||||
return new FormItem
|
return new FormItem
|
||||||
{
|
{
|
||||||
Content = control,
|
Content = control,
|
||||||
[!FormItem.LabelProperty] = control.GetObservable(Form.LabelProperty).ToBinding(),
|
[!FormItem.LabelProperty] = control[!FormItem.LabelProperty],
|
||||||
[!FormItem.IsRequiredProperty] = control.GetObservable(Form.IsRequiredProperty).ToBinding(),
|
[!FormItem.IsRequiredProperty] = control[!FormItem.IsRequiredProperty],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
|
||||||
{
|
|
||||||
base.PrepareContainerForItemOverride(container, item, index);
|
|
||||||
if (container is FormItem formItem)
|
|
||||||
{
|
|
||||||
formItem.LabelWidth = LabelWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,46 +1,93 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Layout;
|
||||||
|
using Avalonia.Reactive;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
|
using Irihi.Avalonia.Shared.Helpers;
|
||||||
|
using Ursa.Common;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
[PseudoClasses(PC_Horizontal, PC_NoLabel)]
|
||||||
public class FormItem: ContentControl
|
public class FormItem: ContentControl
|
||||||
{
|
{
|
||||||
public static readonly StyledProperty<object?> LabelProperty = AvaloniaProperty.Register<FormItem, object?>(
|
public const string PC_Horizontal = ":horizontal";
|
||||||
nameof(Label));
|
public const string PC_NoLabel = ":no-label";
|
||||||
|
|
||||||
public object? Label
|
#region Attached Properties
|
||||||
{
|
public static readonly AttachedProperty<object?> LabelProperty =
|
||||||
get => GetValue(LabelProperty);
|
AvaloniaProperty.RegisterAttached<FormItem, Control, object?>("Label");
|
||||||
set => SetValue(LabelProperty, value);
|
public static void SetLabel(Control obj, object? value) => obj.SetValue(LabelProperty, value);
|
||||||
}
|
public static object? GetLabel(Control obj) => obj.GetValue(LabelProperty);
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsRequiredProperty = AvaloniaProperty.Register<FormItem, bool>(
|
|
||||||
nameof(IsRequired));
|
|
||||||
|
|
||||||
public bool IsRequired
|
public static readonly AttachedProperty<bool> IsRequiredProperty =
|
||||||
{
|
AvaloniaProperty.RegisterAttached<FormItem, Control, bool>("IsRequired");
|
||||||
get => GetValue(IsRequiredProperty);
|
public static void SetIsRequired(Control obj, bool value) => obj.SetValue(IsRequiredProperty, value);
|
||||||
set => SetValue(IsRequiredProperty, value);
|
public static bool GetIsRequired(Control obj) => obj.GetValue(IsRequiredProperty);
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<GridLength> LabelWidthProperty = AvaloniaProperty.Register<FormItem, GridLength>(
|
public static readonly AttachedProperty<bool> NoLabelProperty =
|
||||||
|
AvaloniaProperty.RegisterAttached<FormItem, Control, bool>("NoLabel");
|
||||||
|
|
||||||
|
public static void SetNoLabel(Control obj, bool value) => obj.SetValue(NoLabelProperty, value);
|
||||||
|
public static bool GetNoLabel(Control obj) => obj.GetValue(NoLabelProperty);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private List<IDisposable> _formSubscriptions = new List<IDisposable>();
|
||||||
|
|
||||||
|
public static readonly StyledProperty<double> LabelWidthProperty = AvaloniaProperty.Register<FormItem, double>(
|
||||||
nameof(LabelWidth));
|
nameof(LabelWidth));
|
||||||
|
|
||||||
public GridLength LabelWidth
|
public double LabelWidth
|
||||||
{
|
{
|
||||||
get => GetValue(LabelWidthProperty);
|
get => GetValue(LabelWidthProperty);
|
||||||
set => SetValue(LabelWidthProperty, value);
|
set => SetValue(LabelWidthProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<HorizontalAlignment> LabelAlignmentProperty = AvaloniaProperty.Register<FormItem, HorizontalAlignment>(
|
||||||
|
nameof(LabelAlignment));
|
||||||
|
|
||||||
|
public HorizontalAlignment LabelAlignment
|
||||||
|
{
|
||||||
|
get => GetValue(LabelAlignmentProperty);
|
||||||
|
set => SetValue(LabelAlignmentProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
static FormItem()
|
static FormItem()
|
||||||
{
|
{
|
||||||
LabelWidthProperty.Changed.AddClassHandler<FormItem, GridLength>((x, args) => x.LabelWidthChanged(args));
|
PropertyToPseudoClassMixin.Attach<FormItem>(NoLabelProperty, PC_NoLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LabelWidthChanged(AvaloniaPropertyChangedEventArgs<GridLength> args)
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
GridLength? length = args.GetNewValue<GridLength>();
|
base.OnAttachedToVisualTree(e);
|
||||||
|
var form = this.GetVisualAncestors().OfType<Form>().FirstOrDefault();
|
||||||
|
if (form is not null)
|
||||||
|
{
|
||||||
|
_formSubscriptions.Clear();
|
||||||
|
var labelSubscription = form
|
||||||
|
.GetObservable(Form.LabelWidthProperty)
|
||||||
|
.Subscribe(new AnonymousObserver<GridLength>(length => { LabelWidth = length.IsAbsolute ? length.Value : double.NaN; }));
|
||||||
|
var positionSubscription = form
|
||||||
|
.GetObservable(Form.LabelPositionProperty)
|
||||||
|
.Subscribe(new AnonymousObserver<Position>(position => { PseudoClasses.Set(PC_Horizontal, position == Position.Left);}));
|
||||||
|
var alignmentSubscription = form
|
||||||
|
.GetObservable(Form.LabelAlignmentProperty)
|
||||||
|
.Subscribe(new AnonymousObserver<HorizontalAlignment>(alignment => { LabelAlignment = alignment; }));
|
||||||
|
_formSubscriptions.Add(labelSubscription);
|
||||||
|
_formSubscriptions.Add(positionSubscription);
|
||||||
|
_formSubscriptions.Add(alignmentSubscription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDetachedFromVisualTree(e);
|
||||||
|
foreach (var subscription in _formSubscriptions)
|
||||||
|
{
|
||||||
|
subscription.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Ursa.Controls;
|
|
||||||
|
|
||||||
public class FormPanel
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user