Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Core] Brushes working with DynamicResource #12761

Merged
merged 5 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Controls.Issues.Issue11691"
Title="Issue 11691">
<controls:TestContentPage.Resources>
<ResourceDictionary>

<Color x:Key="PrimaryColor">#0099ff</Color>

<SolidColorBrush x:Key="PrimaryColorBrush" Color="{DynamicResource PrimaryColor}" />

</ResourceDictionary>
</controls:TestContentPage.Resources>
<controls:TestContentPage.Content>
<StackLayout>
<Label
Padding="12"
BackgroundColor="Black"
TextColor="White"
Text="If both polygons are visible, the test has passed."/>
<Label
Text="Polygon with fixed color" />
<Polygon
Fill="Blue"
Points="10,10 100,20 150,45 70,50" />
<Label
Text="Polygon with dynamic color" />
<Polygon
Fill="{DynamicResource PrimaryColorBrush}"
Points="10,10 100,20 150,45 70,50" />
</StackLayout>
</controls:TestContentPage.Content>
</controls:TestContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.Shape)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 11691,
"Polygon Shape doesn't work with DynamicResource color binding",
PlatformAffected.All)]
public partial class Issue11691 : TestContentPage
{
public Issue11691()
{
#if APP
InitializeComponent();
#endif
}

protected override void Init()
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Controls.Issues.Issue11911"
Title="Issue 11911">
<ContentPage.Resources>
<ResourceDictionary>

<Color x:Key="DynamicColor">Red</Color>

</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Label
Padding="12"
BackgroundColor="Black"
TextColor="White"
Text="If the gradient use Green and Red colors, the test has passed."/>
<BoxView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<BoxView.Background>
<LinearGradientBrush
StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="Green" Offset="0.0" />
<GradientStop Color="{DynamicResource DynamicColor}" Offset="1.0" />
</LinearGradientBrush>
</BoxView.Background>
</BoxView>
</StackLayout>
</ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Controls.Issues
{

[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 11911, "[Bug] Brushes can't use DynamicResource", PlatformAffected.All)]
public partial class Issue11911 : ContentPage
{
public Issue11911()
{
#if APP
InitializeComponent();
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,8 @@
<DependentUpon>Issue11081.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue12222.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11911.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11691.xaml.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
Expand Down Expand Up @@ -1951,6 +1953,12 @@
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11081.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11911.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11691.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla27417Xaml.xaml">
Expand Down
18 changes: 18 additions & 0 deletions Xamarin.Forms.Core.UnitTests/BrushUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,23 @@ public void TestBrushTypeConverterWithBrush(string brush)
Assert.True(_converter.CanConvertFrom(typeof(string)));
Assert.NotNull(_converter.ConvertFromInvariantString(brush));
}

[Test]
public void TestBindingContextPropagation()
{
var context = new object();
var linearGradientBrush = new LinearGradientBrush();

var firstStop = new GradientStop { Offset = 0.1f, Color = Color.Red };
var secondStop = new GradientStop { Offset = 1.0f, Color = Color.Blue };

linearGradientBrush.GradientStops.Add(firstStop);
linearGradientBrush.GradientStops.Add(secondStop);

linearGradientBrush.BindingContext = context;

Assert.AreSame(context, firstStop.BindingContext);
Assert.AreSame(context, secondStop.BindingContext);
}
}
}
2 changes: 1 addition & 1 deletion Xamarin.Forms.Core/Brush.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Xamarin.Forms
{
[TypeConverter(typeof(BrushTypeConverter))]
public abstract class Brush : BindableObject
public abstract class Brush : Element
{
public static Brush Default
{
Expand Down
13 changes: 12 additions & 1 deletion Xamarin.Forms.Core/GradientBrush.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Xamarin.Forms
{
Expand Down Expand Up @@ -30,6 +29,14 @@ static void OnGradientStopsChanged(BindableObject bindable, object oldValue, obj
(bindable as GradientBrush)?.UpdateGradientStops(oldValue as GradientStopCollection, newValue as GradientStopCollection);
}

protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();

foreach (var gradientStop in GradientStops)
SetInheritedBindingContext(gradientStop, BindingContext);
}

void UpdateGradientStops(GradientStopCollection oldCollection, GradientStopCollection newCollection)
{
if (oldCollection != null)
Expand All @@ -38,6 +45,7 @@ void UpdateGradientStops(GradientStopCollection oldCollection, GradientStopColle

foreach (var oldStop in oldCollection)
{
oldStop.Parent = null;
oldStop.PropertyChanged -= OnGradientStopPropertyChanged;
}
}
Expand All @@ -49,6 +57,7 @@ void UpdateGradientStops(GradientStopCollection oldCollection, GradientStopColle

foreach (var newStop in newCollection)
{
newStop.Parent = this;
newStop.PropertyChanged += OnGradientStopPropertyChanged;
}
}
Expand All @@ -62,6 +71,7 @@ void OnGradientStopCollectionChanged(object sender, NotifyCollectionChangedEvent
if (!(oldItem is GradientStop oldStop))
continue;

oldStop.Parent = null;
oldStop.PropertyChanged -= OnGradientStopPropertyChanged;
}
}
Expand All @@ -73,6 +83,7 @@ void OnGradientStopCollectionChanged(object sender, NotifyCollectionChangedEvent
if (!(newItem is GradientStop newStop))
continue;

newStop.Parent = this;
newStop.PropertyChanged += OnGradientStopPropertyChanged;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Xamarin.Forms.Core/GradientStop.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Xamarin.Forms
{
public class GradientStop : BindableObject
public class GradientStop : Element
{
public static readonly BindableProperty ColorProperty = BindableProperty.Create(
nameof(Color), typeof(Color), typeof(GradientStop), Color.Default);
Expand Down
13 changes: 11 additions & 2 deletions Xamarin.Forms.Core/Shapes/Shape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ public Shape()
}

public static readonly BindableProperty FillProperty =
BindableProperty.Create(nameof(Fill), typeof(Brush), typeof(Shape), null);
BindableProperty.Create(nameof(Fill), typeof(Brush), typeof(Shape), null,
propertyChanged: OnBrushChanged);

public static readonly BindableProperty StrokeProperty =
BindableProperty.Create(nameof(Stroke), typeof(Brush), typeof(Shape), null);
BindableProperty.Create(nameof(Stroke), typeof(Brush), typeof(Shape), null,
propertyChanged: OnBrushChanged);

public static readonly BindableProperty StrokeThicknessProperty =
BindableProperty.Create(nameof(StrokeThickness), typeof(double), typeof(Shape), 1.0);
Expand Down Expand Up @@ -87,5 +89,12 @@ public Stretch Aspect
set { SetValue(AspectProperty, value); }
get { return (Stretch)GetValue(AspectProperty); }
}

static void OnBrushChanged(BindableObject bindable, object oldValue, object newValue)
Copy link
Member

Choose a reason for hiding this comment

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

you need some code (and unit test) to unparent Brushes

{
((Shape)bindable).UpdateBrushParent((Brush)newValue);
}

void UpdateBrushParent(Brush brush) => brush.Parent = this;
}
}
5 changes: 4 additions & 1 deletion Xamarin.Forms.Core/VisualElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ void NotifyBackgroundChanges()
{
if (Background != null)
{
Background.Parent = this;
Background.PropertyChanged += OnBackgroundChanged;

if (Background is GradientBrush gradientBrush)
Expand All @@ -227,6 +228,7 @@ void StopNotifyingBackgroundChanges()
{
if (Background != null)
{
Background.Parent = null;
Background.PropertyChanged -= OnBackgroundChanged;

if (Background is GradientBrush gradientBrush)
Expand Down Expand Up @@ -821,6 +823,7 @@ public void Unfocus()
protected override void OnBindingContextChanged()
{
PropagateBindingContextToStateTriggers();

base.OnBindingContextChanged();
}

Expand Down Expand Up @@ -983,7 +986,7 @@ void PropagateBindingContextToStateTriggers()
foreach (var stateTrigger in state.StateTriggers)
SetInheritedBindingContext(stateTrigger, BindingContext);
}

void OnFocused() => Focused?.Invoke(this, new FocusEventArgs(this, true));

internal void ChangeVisualStateInternal() => ChangeVisualState();
Expand Down