wip: more properties.

This commit is contained in:
rabbitism
2024-02-18 14:19:13 +08:00
parent a574fb76b4
commit 14c7e6b21f
6 changed files with 120 additions and 18 deletions

View File

@@ -9,10 +9,10 @@
x:CompileBindings="True" x:CompileBindings="True"
x:Class="Ursa.Demo.Pages.FormDemo"> x:Class="Ursa.Demo.Pages.FormDemo">
<StackPanel> <StackPanel>
<u:Form DataContext="{Binding Model}" > <u:Form DataContext="{Binding Model}" LabelWidth="Auto">
<u:FormGroup Header="Information"> <u:FormGroup Header="Information">
<TextBox u:Form.Label="Name" Text="{Binding Name}"/> <TextBox u:Form.Label="Name" Text="{Binding Name}" Width="300"/>
<TextBox u:Form.Label="Email" Text="{Binding Email}"/> <TextBox u:Form.Label="Email" Text="{Binding Email}" Width="300"/>
</u:FormGroup> </u:FormGroup>
<u:FormItem> <u:FormItem>
<CalendarDatePicker u:Form.Label="Date" SelectedDate="{Binding Date}" /> <CalendarDatePicker u:Form.Label="Date" SelectedDate="{Binding Date}" />

View File

@@ -40,4 +40,9 @@ public partial class DataModel : ObservableObject
get => _date; get => _date;
set => SetProperty(ref _date, value); set => SetProperty(ref _date, value);
} }
public DataModel()
{
Date = DateTime.Today;
}
} }

View File

@@ -5,7 +5,9 @@
<ControlTheme x:Key="{x:Type u:Form}" TargetType="u:Form"> <ControlTheme x:Key="{x:Type u:Form}" TargetType="u:Form">
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="u:Form"> <ControlTemplate TargetType="u:Form">
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}"></ItemsPresenter> <DataValidationErrors>
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}"></ItemsPresenter>
</DataValidationErrors>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
</ControlTheme> </ControlTheme>

View File

@@ -1,14 +1,17 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Ursa.Common;
namespace Ursa.Controls; namespace Ursa.Controls;
public class Form: ItemsControl public class Form: ItemsControl
{ {
public static readonly AttachedProperty<string> LabelProperty = #region Attached Properties
AvaloniaProperty.RegisterAttached<Form, Control, string>("Label");
public static void SetLabel(Control obj, string value) => obj.SetValue(LabelProperty, value); public static readonly AttachedProperty<object?> LabelProperty =
public static string GetLabel(Control obj) => obj.GetValue(LabelProperty); AvaloniaProperty.RegisterAttached<Form, Control, object?>("Label");
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 = public static readonly AttachedProperty<bool> IsRequiredProperty =
@@ -16,6 +19,37 @@ public class Form: ItemsControl
public static void SetIsRequired(Control obj, bool value) => obj.SetValue(IsRequiredProperty, value); public static void SetIsRequired(Control obj, bool value) => obj.SetValue(IsRequiredProperty, value);
public static bool GetIsRequired(Control obj) => obj.GetValue(IsRequiredProperty); 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
public static readonly StyledProperty<Position> LabelPositionProperty = AvaloniaProperty.Register<Form, Position>(
nameof(LabelPosition));
/// <summary>
/// Only Left and Top work.
/// </summary>
public Position LabelPosition
{
get => GetValue(LabelPositionProperty);
set => SetValue(LabelPositionProperty, value);
}
public static readonly StyledProperty<Position> LabelAlignmentProperty = AvaloniaProperty.Register<Form, Position>(
nameof(LabelAlignment));
/// <summary>
/// Only Left and Right work.
/// </summary>
public Position LabelAlignment
{
get => GetValue(LabelAlignmentProperty);
set => SetValue(LabelAlignmentProperty, 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,8 +59,30 @@ public class Form: ItemsControl
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
{ {
if (item is not Control control) return new FormItem(); if (item is not Control control) return new FormItem();
string label = GetLabel(control); return new FormItem()
bool isRequired = GetIsRequired(control); {
return new FormItem() { Label = label, IsRequired = isRequired, Content = control }; Content = control,
[!LabelProperty] = control.GetObservable(Form.LabelProperty).ToBinding(),
[!IsRequiredProperty] = control.GetObservable(Form.IsRequiredProperty).ToBinding(),
};
}
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();
}
}
} }
} }

View File

@@ -1,21 +1,41 @@
using Avalonia.Controls; using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
namespace Ursa.Controls; 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;
return item is not FormItem or FormGroup; return item is not FormItem;
} }
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
{ {
if (item is not Control control) return new FormItem(); if (item is not Control control) return new FormItem();
var label = Form.GetLabel(control); return new FormItem
var isRequired = Form.GetIsRequired(control); {
return new FormItem() { Label = label, IsRequired = isRequired, Content = control }; Content = control,
[!FormItem.LabelProperty] = control.GetObservable(Form.LabelProperty).ToBinding(),
[!FormItem.IsRequiredProperty] = control.GetObservable(Form.IsRequiredProperty).ToBinding(),
};
}
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
{
base.PrepareContainerForItemOverride(container, item, index);
if (container is FormItem formItem)
{
formItem.LabelWidth = LabelWidth;
}
} }
} }

View File

@@ -6,10 +6,10 @@ namespace Ursa.Controls;
public class FormItem: ContentControl public class FormItem: ContentControl
{ {
public static readonly StyledProperty<string> LabelProperty = AvaloniaProperty.Register<FormItem, string>( public static readonly StyledProperty<object?> LabelProperty = AvaloniaProperty.Register<FormItem, object?>(
nameof(Label)); nameof(Label));
public string Label public object? Label
{ {
get => GetValue(LabelProperty); get => GetValue(LabelProperty);
set => SetValue(LabelProperty, value); set => SetValue(LabelProperty, value);
@@ -23,5 +23,24 @@ public class FormItem: ContentControl
get => GetValue(IsRequiredProperty); get => GetValue(IsRequiredProperty);
set => SetValue(IsRequiredProperty, value); set => SetValue(IsRequiredProperty, value);
} }
public static readonly StyledProperty<GridLength> LabelWidthProperty = AvaloniaProperty.Register<FormItem, GridLength>(
nameof(LabelWidth));
public GridLength LabelWidth
{
get => GetValue(LabelWidthProperty);
set => SetValue(LabelWidthProperty, value);
}
static FormItem()
{
LabelWidthProperty.Changed.AddClassHandler<FormItem, GridLength>((x, args) => x.LabelWidthChanged(args));
}
private void LabelWidthChanged(AvaloniaPropertyChangedEventArgs<GridLength> args)
{
GridLength? length = args.GetNewValue<GridLength>();
}
} }