Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,8 @@ protected override void OnAttachedTo(View bindable, FrameworkElement platformVie

ApplyTintColor(platformView, bindable, TintColor);

PropertyChanged += OnIconTintColorBehaviorPropertyChanged;
bindable.PropertyChanged += OnElementPropertyChanged;
this.PropertyChanged += (s, e) =>
{
if (e.PropertyName == TintColorProperty.PropertyName)
{
if (currentColorBrush is not null && TintColor is not null)
{
currentColorBrush.Color = TintColor.ToWindowsColor();
}
else
{
ApplyTintColor(platformView, bindable, TintColor);
}
}
};
}

/// <inheritdoc/>
Expand All @@ -50,6 +37,8 @@ protected override void OnDetachedFrom(View bindable, FrameworkElement platformV
base.OnDetachedFrom(bindable, platformView);

bindable.PropertyChanged -= OnElementPropertyChanged;
PropertyChanged -= OnIconTintColorBehaviorPropertyChanged;

RemoveTintColor(platformView);
}

Expand Down Expand Up @@ -83,10 +72,34 @@ static bool TryGetSourceImageUri(WImage? imageControl, IImageElement? imageEleme
return false;
}

void OnIconTintColorBehaviorPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
ArgumentNullException.ThrowIfNull(sender);
var iconTintColorBehavior = (IconTintColorBehavior)sender;

if (iconTintColorBehavior.View is not IView bindable
|| bindable.Handler?.PlatformView is not FrameworkElement platformView)
{
return;
}

if (e.PropertyName == TintColorProperty.PropertyName)
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic inside this handler duplicates the tint-application flow; consider extracting it into a shared helper method to reduce code duplication and improve readability.

Copilot uses AI. Check for mistakes.
{
if (currentColorBrush is not null && TintColor is not null)
{
currentColorBrush.Color = TintColor.ToWindowsColor();
}
else
{
ApplyTintColor(platformView, bindable, TintColor);
}
}
}

void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is not string propertyName
|| sender is not View bindable
|| sender is not IView bindable
|| bindable.Handler?.PlatformView is not FrameworkElement platformView)
{
return;
Expand All @@ -99,7 +112,7 @@ void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs e)
}
}

void ApplyTintColor(FrameworkElement platformView, View element, Color? color)
void ApplyTintColor(FrameworkElement platformView, IView element, Color? color)
{
RemoveTintColor(platformView);

Expand Down Expand Up @@ -128,7 +141,7 @@ void ApplyTintColor(FrameworkElement platformView, View element, Color? color)
}
}

void LoadAndApplyImageTintColor(View element, WImage image, Color color)
void LoadAndApplyImageTintColor(IView element, WImage image, Color color)
{
if (element is IImageElement { Source: UriImageSource uriImageSource })
{
Expand All @@ -140,6 +153,21 @@ void LoadAndApplyImageTintColor(View element, WImage image, Color color)

ApplyTintColor();
}
else if (image.IsLoaded)
{
// Sometimes WImage source doesn't match View source so the image is not ready to be tinted
// We must wait for next ImageOpened event
if (element is IImageElement { Source: FileImageSource fileImageSource }
&& image.Source is BitmapImage bitmapImage
&& Uri.Compare(new Uri($"{bitmapImage.UriSource.Scheme}:///{fileImageSource.File}"), bitmapImage.UriSource, UriComponents.Path, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) is not 0)
{
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After tinting in the ImageOpened handler, unsubscribe this event (e.g., image.ImageOpened -= OnImageOpened;) to avoid memory leaks and duplicate invocations when the image reloads.

Suggested change
{
{
image.ImageOpened -= OnImageOpened; // Unsubscribe first to prevent duplicate subscriptions

Copilot uses AI. Check for mistakes.
image.ImageOpened += OnImageOpened;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please update the IconTintColorBehaviorPage in the sample app to include a use-case that hits this specific line of code where this specific if statement resolves to true?

if (element is IImageElement { Source: FileImageSource fileImageSource }
 				&& image.Source is BitmapImage bitmapImage
 				&& Uri.Compare(new Uri($"{bitmapImage.UriSource.Scheme}:///{fileImageSource.File}"), bitmapImage.UriSource, UriComponents.Path, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) is not 0)

I cannot reach this branch using the Sample App and am unable to test it and verify it works.

}
else
{
ApplyTintColor();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please update the IconTintColorBehaviorPage in the sample app to include a use-case that hits this specific line of code where this specific else block resolves?

else
{
    ApplyTimeColor();
}

I cannot reach this branch using the Sample App and am unable to test it and verify it works.

}
}
else
{
image.ImageOpened += OnImageOpened;
Expand Down Expand Up @@ -178,7 +206,7 @@ void OnImageSizeChanged(object sender, SizeChangedEventArgs e)
}
}

void ApplyImageTintColor(View element, WImage image, Color color)
void ApplyImageTintColor(IView element, WImage image, Color color)
{
if (!TryGetSourceImageUri(image, (IImageElement)element, out var uri))
{
Expand Down
Loading