[UWP] Fix crash on Switch Renderer when a custom renderer provides Color objects instead of Brush (#7760) fixes #7253

* Fixed 7253 -  UWP Switch custom Renderer using custom colors throws exception

* Fixed merge error in the code
This commit is contained in:
Javier Suárez Ruiz 2019-10-02 09:53:15 +02:00 коммит произвёл Rui Marinho
Родитель 54aa9eaf35
Коммит 02c51722e1
5 изменённых файлов: 148 добавлений и 7 удалений

Просмотреть файл

@ -0,0 +1,70 @@
using System.ComponentModel;
using Xamarin.Forms.ControlGallery.WindowsUniversal;
using Xamarin.Forms.Controls.Issues;
using Xamarin.Forms.Platform.UWP;
using WResourceDictionary = Windows.UI.Xaml.ResourceDictionary;
[assembly: ExportRenderer(typeof(CustomSwitch), typeof(CustomSwitchRenderer))]
namespace Xamarin.Forms.ControlGallery.WindowsUniversal
{
// Used in Issue7253.cs
public class CustomSwitchRenderer : SwitchRenderer
{
protected CustomSwitch CustomSwitch => Element as CustomSwitch;
protected CustomSwitchStyle CustomStyle { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
Control.OnContent = null;
Control.OffContent = null;
CustomStyle = new CustomSwitchStyle();
Control.Resources = CustomStyle;
OnElementPropertyChanged(this, new PropertyChangedEventArgs(nameof(CustomSwitch.CustomColor)));
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(CustomSwitch.CustomColor):
CustomStyle.ToggleSwitchStrokeOn(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchStrokeOff(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchKnobFillOn(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchKnobFillOff(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchStrokeOnPointerOver(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchStrokeOffPointerOver(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchKnobFillOffPointerOver(CustomSwitch.CustomColor.ToUwpColor());
CustomStyle.ToggleSwitchKnobFillOnPointerOver(CustomSwitch.CustomColor.ToUwpColor());
break;
}
base.OnElementPropertyChanged(sender, e);
}
protected class CustomSwitchStyle : WResourceDictionary
{
public void ToggleSwitchStrokeOn(Windows.UI.Color c) => this["ToggleSwitchStrokeOn"] = c;
public void ToggleSwitchStrokeOff(Windows.UI.Color c) => this["ToggleSwitchStrokeOff"] = c;
public void ToggleSwitchKnobFillOn(Windows.UI.Color c) => this["ToggleSwitchKnobFillOn"] = c;
public void ToggleSwitchKnobFillOff(Windows.UI.Color c) => this["ToggleSwitchKnobFillOff"] = c;
public void ToggleSwitchStrokeOnPointerOver(Windows.UI.Color c) => this["ToggleSwitchStrokeOnPointerOver"] = c;
public void ToggleSwitchStrokeOffPointerOver(Windows.UI.Color c) => this["ToggleSwitchStrokeOffPointerOver"] = c;
public void ToggleSwitchKnobFillOffPointerOver(Windows.UI.Color c) => this["ToggleSwitchKnobFillOffPointerOver"] = c;
public void ToggleSwitchKnobFillOnPointerOver(Windows.UI.Color c) => this["ToggleSwitchKnobFillOnPointerOver"] = c;
}
}
public static class ColorHelper
{
public static Windows.UI.Color ToUwpColor(this Color xColor) =>
Windows.UI.Color.FromArgb((byte)(xColor.A * 255), (byte)(xColor.R * 255), (byte)(xColor.G * 255), (byte)(xColor.B * 255));
}
}

Просмотреть файл

@ -121,6 +121,7 @@
<ItemGroup>
<Compile Include="AttachedStateEffectRenderer.cs" />
<Compile Include="BorderEffect.cs" />
<Compile Include="CustomSwitchRenderer.cs" />
<Compile Include="DisposePageRenderer.cs" />
<Compile Include="PlatformSpecificCoreGalleryFactory.cs" />
<Compile Include="RegistrarValidationService.cs" />

Просмотреть файл

@ -0,0 +1,60 @@
using Xamarin.Forms.Internals;
using Xamarin.Forms.CustomAttributes;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif
namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7253, "[UWP] Switch custom Renderer using custom colors throws exception", PlatformAffected.UWP)]
#if UITEST
[Category(UITestCategories.ManualReview)]
#endif
public class Issue7253 : TestContentPage
{
public Issue7253()
{
Title = "Issue 7253";
}
protected override void Init()
{
var layout = new StackLayout
{
Padding = new Thickness(12)
};
var instructions = new Label
{
Text = "If the custom Switch below is rendering without problems, the test passes."
};
var customSwitch = new CustomSwitch
{
CustomColor = Color.Red
};
layout.Children.Add(instructions);
layout.Children.Add(customSwitch);
Content = layout;
}
}
[Preserve(AllMembers = true)]
public class CustomSwitch : Switch
{
public static readonly BindableProperty CustomColorProperty =
BindableProperty.Create(nameof(CustomColor), typeof(Color), typeof(CustomSwitch), Color.Black);
public Color CustomColor
{
get => (Color)GetValue(CustomColorProperty);
set => SetValue(CustomColorProperty, value);
}
}
}

Просмотреть файл

@ -23,6 +23,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue5354.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue7253.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7621.xaml.cs">
<SubType>Code</SubType>
</Compile>

Просмотреть файл

@ -131,6 +131,7 @@ namespace Xamarin.Forms.Platform.UWP
return;
var grid = Control.GetFirstDescendant<Windows.UI.Xaml.Controls.Grid>();
if (grid == null)
return;
@ -143,24 +144,32 @@ namespace Xamarin.Forms.Platform.UWP
.KeyFrames.First();
if (_originalThumbOnBrush == null)
_originalThumbOnBrush = (Brush)frame.Value;
{
if (frame.Value is Windows.UI.Color color)
_originalOnColorBrush = new SolidColorBrush(color);
if (frame.Value is Brush brush)
_originalThumbOnBrush = brush;
}
if (!Element.ThumbColor.IsDefault)
frame.Value = new SolidColorBrush(Element.ThumbColor.ToWindowsColor())
{
Opacity = _originalThumbOnBrush.Opacity
};
{
var brush = Element.ThumbColor.ToBrush();
brush.Opacity = _originalThumbOnBrush.Opacity;
frame.Value = brush;
}
else
frame.Value = _originalThumbOnBrush;
var thumb = (Ellipse)grid.FindName("SwitchKnobOn");
if (_originalThumbOnBrush == null)
_originalThumbOnBrush = thumb.Fill;
if (!Element.ThumbColor.IsDefault)
thumb.Fill = new SolidColorBrush(Element.ThumbColor.ToWindowsColor());
thumb.Fill = Element.ThumbColor.ToBrush();
else
thumb.Fill = _originalThumbOnBrush;
}
}
}
}