Fixed crash on UWP Switch (UpdateThumbColor)
authorJavier Suárez Ruiz <javiersuarezruiz@hotmail.com>
Thu, 10 Oct 2019 16:08:43 +0000 (18:08 +0200)
committerJavier Suárez Ruiz <javiersuarezruiz@hotmail.com>
Thu, 10 Oct 2019 16:08:43 +0000 (18:08 +0200)
Xamarin.Forms.Platform.UAP/SwitchRenderer.cs

index 297e6a5..5dbe695 100644 (file)
@@ -5,11 +5,20 @@ using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Media;
 using Windows.UI.Xaml.Media.Animation;
 using Windows.UI.Xaml.Shapes;
+using WGrid = Windows.UI.Xaml.Controls.Grid;
+using WRectangle = Windows.UI.Xaml.Shapes.Rectangle;
+using WVisualStateManager = Windows.UI.Xaml.VisualStateManager;
 
 namespace Xamarin.Forms.Platform.UWP
 {
        public class SwitchRenderer : ViewRenderer<Switch, ToggleSwitch>
        {
+               const string ToggleSwitchCommonStates = "CommonStates";
+               const string ToggleSwitchPointerOver = "PointerOver";
+               const string ToggleSwitchKnobBounds = "SwitchKnobBounds";
+               const string ToggleSwitchKnobOn = "SwitchKnobOn";
+               const string ToggleSwitchFillMode = "Fill";
+       
                Brush _originalOnHoverColor;
                Brush _originalOnColorBrush;
                Brush _originalThumbOnBrush;
@@ -78,51 +87,58 @@ namespace Xamarin.Forms.Platform.UWP
                        if (Control == null)
                                return;
 
-                       var grid = Control.GetFirstDescendant<Windows.UI.Xaml.Controls.Grid>();
+                       var grid = Control.GetFirstDescendant<WGrid>();
                        if (grid == null)
                                return;
 
-                       var groups = Windows.UI.Xaml.VisualStateManager.GetVisualStateGroups(grid);
+                       var groups = WVisualStateManager.GetVisualStateGroups(grid);
                        foreach (var group in groups)
                        {
-                               if (group.Name != "CommonStates")
+                               if (group.Name != ToggleSwitchCommonStates)
                                        continue;
 
                                foreach (var state in group.States)
                                {
-                                       if (state.Name != "PointerOver")
+                                       if (state.Name != ToggleSwitchPointerOver)
                                                continue;
 
                                        foreach (var timeline in state.Storyboard.Children.OfType<ObjectAnimationUsingKeyFrames>())
                                        {
                                                var property = Storyboard.GetTargetProperty(timeline);
                                                var target = Storyboard.GetTargetName(timeline);
-                                               if (target == "SwitchKnobBounds" && property == "Fill")
-                                               {
-                                                       var frame = timeline.KeyFrames.First();
-
-                                                       if (_originalOnHoverColor == null)
-                                                               _originalOnHoverColor = (Brush)frame.Value;
 
-                                                       if (!Element.OnColor.IsDefault)
-                                                               frame.Value = new SolidColorBrush(Element.OnColor.ToWindowsColor()) { Opacity = _originalOnHoverColor.Opacity };
-                                                       else
-                                                               frame.Value = _originalOnHoverColor;
+                                               if (target == ToggleSwitchKnobBounds && property == ToggleSwitchFillMode)
+                                               {
+                                                       var frame = timeline.KeyFrames.FirstOrDefault();
+
+                                                       if (frame != null)
+                                                       {
+                                                               if (_originalOnHoverColor == null)
+                                                                       _originalOnHoverColor = frame.Value as Brush;
+
+                                                               if (!Element.OnColor.IsDefault)
+                                                                       frame.Value = new SolidColorBrush(Element.OnColor.ToWindowsColor()) { Opacity = _originalOnHoverColor.Opacity };
+                                                               else
+                                                                       frame.Value = _originalOnHoverColor;
+                                                       }
                                                        break;
                                                }
                                        }
                                }
                        }
 
-                       var rect = Control.GetDescendantsByName<Windows.UI.Xaml.Shapes.Rectangle>("SwitchKnobBounds").First();
+                       var rect = Control.GetDescendantsByName<WRectangle>(ToggleSwitchKnobBounds).FirstOrDefault();
 
-                       if (_originalOnColorBrush == null)
-                               _originalOnColorBrush = rect.Fill;
+                       if (rect != null)
+                       {
+                               if (_originalOnColorBrush == null)
+                                       _originalOnColorBrush = rect.Fill;
 
-                       if (!Element.OnColor.IsDefault)
-                               rect.Fill = new SolidColorBrush(Element.OnColor.ToWindowsColor());
-                       else
-                               rect.Fill = _originalOnColorBrush;
+                               if (!Element.OnColor.IsDefault)
+                                       rect.Fill = new SolidColorBrush(Element.OnColor.ToWindowsColor());
+                               else
+                                       rect.Fill = _originalOnColorBrush;
+                       }
                }
 
                void UpdateThumbColor()
@@ -130,37 +146,68 @@ namespace Xamarin.Forms.Platform.UWP
                        if (Control == null)
                                return;
 
-                       var grid = Control.GetFirstDescendant<Windows.UI.Xaml.Controls.Grid>();
+                       var grid = Control.GetFirstDescendant<WGrid>();
+
                        if (grid == null)
                                return;
 
-                       ObjectKeyFrame frame = Windows.UI.Xaml.VisualStateManager.GetVisualStateGroups(grid)
-                               .First(g => g.Name == "CommonStates")
-                               .States.First(s => s.Name == "PointerOver")
-                               .Storyboard.Children.OfType<ObjectAnimationUsingKeyFrames>().First(
-                                       t => Storyboard.GetTargetName(t) == "SwitchKnobOn" &&
-                                                Storyboard.GetTargetProperty(t) == "Fill")
-                               .KeyFrames.First();
+                       var groups = WVisualStateManager.GetVisualStateGroups(grid);
 
-                       if (_originalThumbOnBrush == null)
-                               _originalThumbOnBrush = (Brush)frame.Value;
+                       foreach (var group in groups)
+                       {
+                               if (group.Name != ToggleSwitchCommonStates)
+                                       continue;
 
-                       if (!Element.ThumbColor.IsDefault)
-                               frame.Value = new SolidColorBrush(Element.ThumbColor.ToWindowsColor())
+                               foreach (var state in group.States)
                                {
-                                       Opacity = _originalThumbOnBrush.Opacity
-                               };
-                       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());
-                       else
-                               thumb.Fill = _originalThumbOnBrush;
+                                       if (state.Name != ToggleSwitchPointerOver)
+                                               continue;
+
+                                       foreach (var timeline in state.Storyboard.Children.OfType<ObjectAnimationUsingKeyFrames>())
+                                       {
+                                               var property = Storyboard.GetTargetProperty(timeline);
+                                               var target = Storyboard.GetTargetName(timeline);
+
+                                               if ((target == ToggleSwitchKnobOn) && (property == ToggleSwitchFillMode))
+                                               {
+                                                       var frame = timeline.KeyFrames.FirstOrDefault();
+
+                                                       if (frame != null)
+                                                       {
+                                                               if (_originalThumbOnBrush == null)
+                                                               {
+                                                                       if (frame.Value is Windows.UI.Color color)
+                                                                               _originalOnColorBrush = new SolidColorBrush(color);
+
+                                                                       if (frame.Value is Brush brush)
+                                                                               _originalThumbOnBrush = brush;
+                                                               }
+
+                                                               if (!Element.ThumbColor.IsDefault)
+                                                               {
+                                                                       var brush = Element.ThumbColor.ToBrush();
+                                                                       brush.Opacity = _originalThumbOnBrush.Opacity;
+                                                                       frame.Value = brush;
+                                                               }
+                                                               else
+                                                                       frame.Value = _originalThumbOnBrush;
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (grid.FindName(ToggleSwitchKnobOn) is Ellipse thumb)
+                       {
+                               if (_originalThumbOnBrush == null)
+                                       _originalThumbOnBrush = thumb.Fill;
+
+                               if (!Element.ThumbColor.IsDefault)
+                                       thumb.Fill = Element.ThumbColor.ToBrush();
+                               else
+                                       thumb.Fill = _originalThumbOnBrush;
+                       }
                }
        }
-}
+}
\ No newline at end of file