diff --git a/Toolkit.Avalonia/FrameHandler.cs b/Toolkit.Avalonia/FrameHandler.cs
index 3dbcdd8..f855733 100644
--- a/Toolkit.Avalonia/FrameHandler.cs
+++ b/Toolkit.Avalonia/FrameHandler.cs
@@ -168,12 +168,13 @@ public class FrameHandler :
}
}
}
-
- frame.NavigateFromObject(control, navigationOptions);
foreach (Action postAction in postNavigateActions)
{
postAction.Invoke();
}
+
+ frame.NavigateFromObject(control, navigationOptions);
+
}
}
diff --git a/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPicture.axaml b/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPicture.axaml
index a0741ce..f1f81b5 100644
--- a/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPicture.axaml
+++ b/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPicture.axaml
@@ -4,19 +4,19 @@
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
-
+
-
+
-
+
-
+
@@ -27,18 +27,19 @@
0,-4,-4,0
+
+
+
+
-
-
-
BadgeGlyphProperty =
@@ -36,11 +37,12 @@ public class PersonPicture : TemplatedControl
private static readonly StyledProperty TemplateSettingsProperty =
AvaloniaProperty.Register(nameof(TemplateSettings));
+ private readonly ImageBrush? badgeImageBrush;
private FontIcon? badgeGlyphIcon;
- private ImageBrush? badgeImageBrush;
private TextBlock? badgeNumberTextBlock;
private Ellipse? badgingBackgroundEllipse;
private Ellipse? badgingEllipse;
+ private PersonPictureColourGenerator colourGenerator = new(hue: 210, saturation: 0.8f, lightness: 0.6f);
private string? displayNameInitials;
private TextBlock? initialsTextBlock;
@@ -335,6 +337,12 @@ public class PersonPicture : TemplatedControl
PersonPictureTemplateSettings templateSettings = TemplateSettings;
templateSettings.ActualInitials = initials;
+ if (DisplayName is { Length: > 0 })
+ {
+ Color rgb = colourGenerator.Create(DisplayName);
+ SetValue(BackgroundProperty, new SolidColorBrush(Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B)));
+ }
+
if (imageSource is not null)
{
ImageBrush? imageBrush = templateSettings.ActualImageBrush;
diff --git a/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPictureColourGenerator.cs b/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPictureColourGenerator.cs
new file mode 100644
index 0000000..0eca004
--- /dev/null
+++ b/Toolkit.UI.Controls.Avalonia/PersonPicture/PersonPictureColourGenerator.cs
@@ -0,0 +1,75 @@
+using Avalonia.Media;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Toolkit.UI.Controls.Avalonia;
+
+public class PersonPictureColourGenerator
+{
+ private readonly float hue;
+ private readonly float saturation;
+ private readonly float lightness;
+ private const float minLightness = 0.2f;
+ private const float maxLightness = 0.8f;
+
+ public PersonPictureColourGenerator(float hue = 210,
+ float saturation = 0.8f,
+ float lightness = 0.6f)
+ {
+ this.hue = hue;
+ this.saturation = saturation;
+ this.lightness = lightness;
+ }
+
+ public Color Create(string input)
+ {
+ byte[] hashBytes = GetHash(input);
+
+ float h = (hashBytes[0] + hue) % 360;
+ float s = (hashBytes[1] / 255.0f) * saturation;
+ float l = EnsureNonExtremeLightness((hashBytes[2] / 255.0f) * lightness);
+
+ (byte r, byte g, byte b) = HslToRgb(h, s, l);
+
+ return Color.FromRgb(r, g, b);
+ }
+
+ private byte[] GetHash(string input) =>
+ SHA256.HashData(Encoding.UTF8.GetBytes(input));
+
+ private float EnsureNonExtremeLightness(float calculatedLightness) =>
+ calculatedLightness < minLightness ? minLightness : calculatedLightness > maxLightness ?
+ maxLightness : calculatedLightness;
+
+ private (byte r, byte g, byte b) HslToRgb(float h, float s, float l)
+ {
+ h /= 360;
+ float r, g, b;
+
+ if (s == 0)
+ {
+ r = g = b = l;
+ }
+ else
+ {
+ float q = l < 0.5f ? l * (1 + s) : l + s - l * s;
+ float p = 2 * l - q;
+
+ r = HueToRgb(p, q, h + 1.0f / 3.0f);
+ g = HueToRgb(p, q, h);
+ b = HueToRgb(p, q, h - 1.0f / 3.0f);
+ }
+
+ return ((byte)(r * 255), (byte)(g * 255), (byte)(b * 255));
+ }
+
+ private float HueToRgb(float p, float q, float t)
+ {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1.0f / 6.0f) return p + (q - p) * 6 * t;
+ if (t < 1.0f / 2.0f) return q;
+ if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6;
+ return p;
+ }
+}