added Toolkit.UI.Avalonia
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class AttachedBehavior : Trigger
|
||||||
|
{
|
||||||
|
protected override void OnAttachedToVisualTree()
|
||||||
|
{
|
||||||
|
Interaction.ExecuteActions(AssociatedObject, Actions, null);
|
||||||
|
base.OnAttachedToVisualTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
public class ComparisonCondition :
|
||||||
|
AvaloniaObject,
|
||||||
|
ICondition
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<object> LeftOperandProperty =
|
||||||
|
AvaloniaProperty.Register<ComparisonCondition, object>(nameof(LeftOperand));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<ComparisonConditionType> OperatorProperty =
|
||||||
|
AvaloniaProperty.Register<ComparisonCondition, ComparisonConditionType>(nameof(Operator));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object> RightOperandProperty =
|
||||||
|
AvaloniaProperty.Register<ComparisonCondition, object>(nameof(RightOperand));
|
||||||
|
|
||||||
|
public object LeftOperand
|
||||||
|
{
|
||||||
|
get => GetValue(LeftOperandProperty);
|
||||||
|
set => SetValue(LeftOperandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object RightOperand
|
||||||
|
{
|
||||||
|
get => GetValue(RightOperandProperty);
|
||||||
|
set => SetValue(RightOperandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparisonConditionType Operator
|
||||||
|
{
|
||||||
|
get => GetValue(OperatorProperty);
|
||||||
|
set => SetValue(OperatorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Evaluate() => ComparisonLogic.Evaluate(LeftOperand,
|
||||||
|
Operator, RightOperand);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
internal static class ComparisonLogic
|
||||||
|
{
|
||||||
|
internal static bool Evaluate(object leftOperand,
|
||||||
|
ComparisonConditionType operatorType,
|
||||||
|
object? rightOperand)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (leftOperand != null)
|
||||||
|
{
|
||||||
|
Type leftType = leftOperand.GetType();
|
||||||
|
|
||||||
|
if (rightOperand != null)
|
||||||
|
{
|
||||||
|
TypeConverter typeConverter = TypeDescriptor.GetConverter(leftType);
|
||||||
|
rightOperand = typeConverter.ConvertFrom(rightOperand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (leftOperand is IComparable leftComparableOperand &&
|
||||||
|
rightOperand is IComparable rightComparableOperand)
|
||||||
|
{
|
||||||
|
return EvaluateComparable(leftComparableOperand, operatorType, rightComparableOperand);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (operatorType)
|
||||||
|
{
|
||||||
|
case ComparisonConditionType.Equal:
|
||||||
|
result = Equals(leftOperand, rightOperand);
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.NotEqual:
|
||||||
|
result = !Equals(leftOperand, rightOperand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool EvaluateComparable(IComparable leftOperand,
|
||||||
|
ComparisonConditionType operatorType,
|
||||||
|
IComparable rightOperand)
|
||||||
|
{
|
||||||
|
object? convertedOperand = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
convertedOperand = Convert.ChangeType(rightOperand, leftOperand.GetType(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (InvalidCastException)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convertedOperand == null)
|
||||||
|
{
|
||||||
|
return operatorType == ComparisonConditionType.NotEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comparison = leftOperand.CompareTo((IComparable)convertedOperand);
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (operatorType)
|
||||||
|
{
|
||||||
|
case ComparisonConditionType.Equal:
|
||||||
|
result = comparison == 0;
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.GreaterThan:
|
||||||
|
result = comparison > 0;
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.GreaterThanOrEqual:
|
||||||
|
result = comparison >= 0;
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.LessThan:
|
||||||
|
result = comparison < 0;
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.LessThanOrEqual:
|
||||||
|
result = comparison <= 0;
|
||||||
|
break;
|
||||||
|
case ComparisonConditionType.NotEqual:
|
||||||
|
result = comparison != 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ConditionAction :
|
||||||
|
AvaloniaObject,
|
||||||
|
IAction
|
||||||
|
{
|
||||||
|
public static readonly DirectProperty<ConditionAction, ActionCollection> ActionsProperty =
|
||||||
|
AvaloniaProperty.RegisterDirect<ConditionAction, ActionCollection>(nameof(Actions),
|
||||||
|
x => x.Actions);
|
||||||
|
|
||||||
|
public static readonly StyledProperty<ICondition> ConditionProperty =
|
||||||
|
AvaloniaProperty.Register<ConditionAction, ICondition>(nameof(Condition));
|
||||||
|
|
||||||
|
private ActionCollection? actions;
|
||||||
|
|
||||||
|
[Content]
|
||||||
|
public ActionCollection Actions => actions ??= [];
|
||||||
|
|
||||||
|
public ICondition Condition
|
||||||
|
{
|
||||||
|
get => GetValue(ConditionProperty);
|
||||||
|
set => SetValue(ConditionProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? Execute(object? sender, object? parameter)
|
||||||
|
{
|
||||||
|
bool? result = Condition?.Evaluate();
|
||||||
|
if (result is true)
|
||||||
|
{
|
||||||
|
Interaction.ExecuteActions(sender, Actions, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ConditionCollection :
|
||||||
|
ObservableCollection<ComparisonCondition>
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
using Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ConditionalExpression :
|
||||||
|
AvaloniaObject,
|
||||||
|
ICondition
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<ConditionCollection> ConditionsProperty =
|
||||||
|
AvaloniaProperty.Register<ConditionalExpression, ConditionCollection>(nameof(Conditions));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<ForwardChaining> ForwardChainingProperty =
|
||||||
|
AvaloniaProperty.Register<ConditionalExpression, ForwardChaining>(nameof(ForwardChaining));
|
||||||
|
|
||||||
|
public ConditionalExpression() =>
|
||||||
|
SetValue(ConditionsProperty, []);
|
||||||
|
|
||||||
|
[Content]
|
||||||
|
public ConditionCollection Conditions =>
|
||||||
|
GetValue(ConditionsProperty);
|
||||||
|
|
||||||
|
public ForwardChaining ForwardChaining
|
||||||
|
{
|
||||||
|
get => GetValue(ForwardChainingProperty);
|
||||||
|
set => SetValue(ForwardChainingProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Evaluate()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
foreach (ComparisonCondition operation in this.Conditions)
|
||||||
|
{
|
||||||
|
result = operation.Evaluate();
|
||||||
|
|
||||||
|
if (result == false && ForwardChaining == ForwardChaining.And)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == true && ForwardChaining == ForwardChaining.Or)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public enum ForwardChaining
|
||||||
|
{
|
||||||
|
And,
|
||||||
|
Or
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public interface ICondition
|
||||||
|
{
|
||||||
|
bool Evaluate();
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Metadata;
|
||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class NavigateAction :
|
||||||
|
AvaloniaObject,
|
||||||
|
IAction
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<object> ContextProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateAction, object>(nameof(Context));
|
||||||
|
|
||||||
|
public static readonly DirectProperty<NavigateAction, ParameterBindingCollection> ParameterBindingsProperty =
|
||||||
|
AvaloniaProperty.RegisterDirect<NavigateAction, ParameterBindingCollection>(nameof(ParameterBindings),
|
||||||
|
x => x.ParameterBindings);
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object[]?> ParametersProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateAction, object[]?>(nameof(Parameters));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> RouteProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateAction, string>(nameof(Route));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> ScopeProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateAction, string>(nameof(Scope));
|
||||||
|
|
||||||
|
private ParameterBindingCollection parameterCollection = [];
|
||||||
|
|
||||||
|
public event EventHandler? Navigated;
|
||||||
|
|
||||||
|
public object Context
|
||||||
|
{
|
||||||
|
get => GetValue(ContextProperty);
|
||||||
|
set => SetValue(ContextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Content]
|
||||||
|
public ParameterBindingCollection ParameterBindings =>
|
||||||
|
parameterCollection ??= [];
|
||||||
|
|
||||||
|
public object[]? Parameters
|
||||||
|
{
|
||||||
|
get => GetValue(ParametersProperty);
|
||||||
|
set => SetValue(ParametersProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Route
|
||||||
|
{
|
||||||
|
get => GetValue(RouteProperty);
|
||||||
|
set => SetValue(RouteProperty, value);
|
||||||
|
}
|
||||||
|
public string Scope
|
||||||
|
{
|
||||||
|
get => GetValue(ScopeProperty);
|
||||||
|
set => SetValue(ScopeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Execute(object? sender,
|
||||||
|
object? parameter)
|
||||||
|
{
|
||||||
|
if (sender is TemplatedControl control)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> arguments =
|
||||||
|
new(StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
|
if (control.DataContext is IObservableViewModel observableViewModel)
|
||||||
|
{
|
||||||
|
object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(), ..
|
||||||
|
ParameterBindings is { Count: > 0 } ?
|
||||||
|
ParameterBindings.Select(binding => new KeyValuePair<string, object>(binding.Key, binding.Value)).ToArray() :
|
||||||
|
Enumerable.Empty<KeyValuePair<string, object>>()];
|
||||||
|
|
||||||
|
observableViewModel.Publisher.Publish(new Navigate(Route, Context
|
||||||
|
?? null, Scope ?? null, control.DataContext, Navigated, parameters));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class NavigateBackAction :
|
||||||
|
AvaloniaObject,
|
||||||
|
IAction
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<string> ContextProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Context));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<string> ScopeProperty =
|
||||||
|
AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Scope));
|
||||||
|
|
||||||
|
public string Context
|
||||||
|
{
|
||||||
|
get => GetValue(ContextProperty);
|
||||||
|
set => SetValue(ContextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Scope
|
||||||
|
{
|
||||||
|
get => GetValue(ScopeProperty);
|
||||||
|
set => SetValue(ScopeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Execute(object? sender,
|
||||||
|
object? parameter)
|
||||||
|
{
|
||||||
|
if (sender is TemplatedControl control)
|
||||||
|
{
|
||||||
|
if (control.DataContext is IObservableViewModel observableViewModel)
|
||||||
|
{
|
||||||
|
observableViewModel.Publisher.Publish(new NavigateBack(Context
|
||||||
|
?? null, Scope ?? null)).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using Avalonia;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ParameterBinding :
|
||||||
|
AvaloniaObject
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<string> KeyProperty =
|
||||||
|
AvaloniaProperty.Register<ParameterBinding, string>(nameof(Key));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object> ValueProperty =
|
||||||
|
AvaloniaProperty.Register<ParameterBinding, object>(nameof(Value));
|
||||||
|
|
||||||
|
public string Key
|
||||||
|
{
|
||||||
|
get => GetValue(KeyProperty);
|
||||||
|
set => SetValue(KeyProperty, value);
|
||||||
|
}
|
||||||
|
public object Value
|
||||||
|
{
|
||||||
|
get => GetValue(ValueProperty);
|
||||||
|
set => SetValue(ValueProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ParameterBindingCollection :
|
||||||
|
ObservableCollection<ParameterBinding>;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Avalonia" Version="11.1.0-beta1" />
|
||||||
|
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.9.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Toolkit.Foundation\Toolkit.Foundation.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.4.33110.190
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolkit.Foundation", "Toolkit.Foundation\Toolkit.Foundation.csproj", "{66968F8D-689E-49D8-9370-DFF099C56202}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolkit.Foundation", "Toolkit.Foundation\Toolkit.Foundation.csproj", "{66968F8D-689E-49D8-9370-DFF099C56202}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolkit.UI.Avalonia", "Toolkit.UI.Avalonia\Toolkit.UI.Avalonia.csproj", "{E091FA94-2F15-403A-98D1-4557C2FF9A02}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -15,6 +17,10 @@ Global
|
|||||||
{66968F8D-689E-49D8-9370-DFF099C56202}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{66968F8D-689E-49D8-9370-DFF099C56202}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.Build.0 = Release|Any CPU
|
{66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E091FA94-2F15-403A-98D1-4557C2FF9A02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E091FA94-2F15-403A-98D1-4557C2FF9A02}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E091FA94-2F15-403A-98D1-4557C2FF9A02}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E091FA94-2F15-403A-98D1-4557C2FF9A02}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user