This commit is contained in:
Dan Clark
2024-11-23 21:41:59 +00:00
parent e809c22cb7
commit 911ed375b4
17 changed files with 311 additions and 18 deletions
+46
View File
@@ -0,0 +1,46 @@
using Microsoft.UI.Xaml;
using Microsoft.Xaml.Interactions.Core;
using Toolkit.Foundation;
namespace Toolkit.UI.WinUI;
public class ComparisonCondition :
DependencyObject,
ICondition
{
public static readonly DependencyProperty LeftOperandProperty =
DependencyProperty.Register(nameof(LeftOperand),
typeof(object), typeof(ComparisonCondition),
new PropertyMetadata(null));
public static readonly DependencyProperty OperatorProperty =
DependencyProperty.Register(nameof(Operator),
typeof(ComparisonConditionType), typeof(ComparisonCondition),
new PropertyMetadata(null));
public static readonly DependencyProperty RightOperandProperty =
DependencyProperty.Register(nameof(RightOperand),
typeof(object), typeof(ComparisonCondition),
new PropertyMetadata(null));
public object LeftOperand
{
get => GetValue(LeftOperandProperty);
set => SetValue(LeftOperandProperty, value);
}
public object RightOperand
{
get => GetValue(RightOperandProperty);
set => SetValue(RightOperandProperty, value);
}
public ComparisonConditionType Operator
{
get => (ComparisonConditionType)GetValue(OperatorProperty);
set => SetValue(OperatorProperty, value);
}
public bool Evaluate() =>
ComparisonLogic.Evaluate(LeftOperand, Operator, RightOperand);
}
+100
View File
@@ -0,0 +1,100 @@
using Microsoft.Xaml.Interactions.Core;
using System;
using System.ComponentModel;
using System.Globalization;
namespace Toolkit.UI.WinUI;
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;
}
}
+42
View File
@@ -0,0 +1,42 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Markup;
using Microsoft.Xaml.Interactivity;
using Toolkit.Foundation;
namespace Toolkit.UI.WinUI;
[ContentProperty(Name = nameof(Actions))]
public class ConditionAction :
DependencyObject,
IAction
{
public static readonly DependencyProperty ActionsProperty =
DependencyProperty.Register(nameof(Actions),
typeof(ActionCollection), typeof(ConditionAction),
new PropertyMetadata(null));
public static readonly DependencyProperty ConditionProperty =
DependencyProperty.Register(nameof(Condition),
typeof(ICondition), typeof(ConditionAction),
new PropertyMetadata(null));
private ActionCollection? actions;
public ActionCollection Actions => actions ??= [];
public ICondition? Condition
{
get => (ICondition?)GetValue(ConditionProperty);
set => SetValue(ConditionProperty, value);
}
public object? Execute(object? sender, object? parameter)
{
if (Condition?.Evaluate() == true)
{
Interaction.ExecuteActions(sender, Actions, parameter);
}
return true;
}
}
+8
View File
@@ -0,0 +1,8 @@
using System.Collections.ObjectModel;
namespace Toolkit.UI.WinUI;
public class ConditionCollection :
ObservableCollection<ComparisonCondition>
{
}
+56
View File
@@ -0,0 +1,56 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Markup;
using Toolkit.Foundation;
namespace Toolkit.UI.WinUI;
[ContentProperty(Name = nameof(Conditions))]
public class ConditionalExpression :
DependencyObject,
ICondition
{
public static readonly DependencyProperty ConditionsProperty =
DependencyProperty.Register(nameof(Conditions),
typeof(ConditionCollection), typeof(ConditionalExpression),
new PropertyMetadata(new ConditionCollection()));
public static readonly DependencyProperty ForwardChainingProperty =
DependencyProperty.Register(nameof(ForwardChaining),
typeof(ForwardChaining), typeof(ConditionalExpression),
new PropertyMetadata(ForwardChaining.And));
public ConditionalExpression()
{
SetValue(ConditionsProperty, new ConditionCollection());
}
public ConditionCollection Conditions =>
(ConditionCollection)GetValue(ConditionsProperty);
public ForwardChaining ForwardChaining
{
get => (ForwardChaining)GetValue(ForwardChainingProperty);
set => SetValue(ForwardChainingProperty, value);
}
public bool Evaluate()
{
bool result = false;
foreach (var operation in Conditions)
{
result = operation.Evaluate();
if (!result && ForwardChaining == ForwardChaining.And)
{
return false;
}
if (result && ForwardChaining == ForwardChaining.Or)
{
return true;
}
}
return result;
}
}