|
|
@ -17,6 +17,10 @@ namespace Avalonia |
|
|
AvaloniaProperty.RegisterAttached<StyledElement, string>( |
|
|
AvaloniaProperty.RegisterAttached<StyledElement, string>( |
|
|
"Classes", typeof(ClassBindingManager), ""); |
|
|
"Classes", typeof(ClassBindingManager), ""); |
|
|
|
|
|
|
|
|
|
|
|
public static readonly AttachedProperty<HashSet<string>?> BoundClassesProperty = |
|
|
|
|
|
AvaloniaProperty.RegisterAttached<StyledElement, HashSet<string>?>( |
|
|
|
|
|
"BoundClasses", typeof(ClassBindingManager)); |
|
|
|
|
|
|
|
|
public static void SetClasses(StyledElement element, string value) |
|
|
public static void SetClasses(StyledElement element, string value) |
|
|
{ |
|
|
{ |
|
|
_ = element ?? throw new ArgumentNullException(nameof(element)); |
|
|
_ = element ?? throw new ArgumentNullException(nameof(element)); |
|
|
@ -29,6 +33,18 @@ namespace Avalonia |
|
|
return element.GetValue(ClassesProperty); |
|
|
return element.GetValue(ClassesProperty); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void SetBoundClasses(StyledElement element, HashSet<string>? value) |
|
|
|
|
|
{ |
|
|
|
|
|
_ = element ?? throw new ArgumentNullException(nameof(element)); |
|
|
|
|
|
element.SetValue(BoundClassesProperty, value); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static HashSet<string>? GetBoundClasses(StyledElement element) |
|
|
|
|
|
{ |
|
|
|
|
|
_ = element ?? throw new ArgumentNullException(nameof(element)); |
|
|
|
|
|
return element.GetValue(BoundClassesProperty); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static ClassBindingManager() |
|
|
static ClassBindingManager() |
|
|
{ |
|
|
{ |
|
|
ClassesProperty.Changed.AddClassHandler<StyledElement, string>(ClassesPropertyChanged); |
|
|
ClassesProperty.Changed.AddClassHandler<StyledElement, string>(ClassesPropertyChanged); |
|
|
@ -36,13 +52,28 @@ namespace Avalonia |
|
|
|
|
|
|
|
|
private static void ClassesPropertyChanged(StyledElement sender, AvaloniaPropertyChangedEventArgs<string> e) |
|
|
private static void ClassesPropertyChanged(StyledElement sender, AvaloniaPropertyChangedEventArgs<string> e) |
|
|
{ |
|
|
{ |
|
|
|
|
|
var boundClasses = GetBoundClasses(sender); |
|
|
|
|
|
|
|
|
var newValue = e.GetNewValue<string?>() ?? ""; |
|
|
var newValue = e.GetNewValue<string?>() ?? ""; |
|
|
var newValues = newValue.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); |
|
|
var newValues = newValue.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); |
|
|
var currentValues = sender.Classes.Where(c => !c.StartsWith(":", StringComparison.Ordinal)); |
|
|
var currentValues = sender.Classes |
|
|
|
|
|
.Where(c => !c.StartsWith(":", StringComparison.Ordinal) && boundClasses?.Contains(c) != true) |
|
|
|
|
|
.ToList(); |
|
|
if (currentValues.SequenceEqual(newValues)) |
|
|
if (currentValues.SequenceEqual(newValues)) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
sender.Classes.Replace(newValues); |
|
|
sender.Classes.Replace(currentValues, newValues); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void AddBoundClass(StyledElement target, string className) |
|
|
|
|
|
{ |
|
|
|
|
|
var boundClasses = GetBoundClasses(target); |
|
|
|
|
|
if (boundClasses == null) |
|
|
|
|
|
{ |
|
|
|
|
|
boundClasses = []; |
|
|
|
|
|
SetBoundClasses(target, boundClasses); |
|
|
|
|
|
} |
|
|
|
|
|
boundClasses.Add(className); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static IDisposable BindClasses(StyledElement target, BindingBase source, object anchor) |
|
|
public static IDisposable BindClasses(StyledElement target, BindingBase source, object anchor) |
|
|
@ -50,8 +81,15 @@ namespace Avalonia |
|
|
return target.Bind(ClassesProperty, source); |
|
|
return target.Bind(ClassesProperty, source); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void SetClass(StyledElement target, string className, bool value) |
|
|
|
|
|
{ |
|
|
|
|
|
AddBoundClass(target, className); |
|
|
|
|
|
target.Classes.Set(className, value); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public static IDisposable BindClass(StyledElement target, string className, BindingBase source, object anchor) |
|
|
public static IDisposable BindClass(StyledElement target, string className, BindingBase source, object anchor) |
|
|
{ |
|
|
{ |
|
|
|
|
|
AddBoundClass(target, className); |
|
|
var prop = GetClassProperty(className); |
|
|
var prop = GetClassProperty(className); |
|
|
return target.Bind(prop, source); |
|
|
return target.Bind(prop, source); |
|
|
} |
|
|
} |
|
|
@ -63,8 +101,8 @@ namespace Avalonia |
|
|
var prop = AvaloniaProperty.Register<StyledElement, bool>(ClassPropertyPrefix + className); |
|
|
var prop = AvaloniaProperty.Register<StyledElement, bool>(ClassPropertyPrefix + className); |
|
|
prop.Changed.Subscribe(args => |
|
|
prop.Changed.Subscribe(args => |
|
|
{ |
|
|
{ |
|
|
var classes = ((StyledElement)args.Sender).Classes; |
|
|
var sender = (StyledElement)args.Sender; |
|
|
classes.Set(className, args.NewValue.GetValueOrDefault()); |
|
|
SetClass(sender, className, args.NewValue.GetValueOrDefault()); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return prop; |
|
|
return prop; |
|
|
|