Use a prototype TextBlock to resolve theme resources on Windows (#703)
authorE.Z. Hart <hartez@users.noreply.github.com>
Thu, 26 Jan 2017 18:51:28 +0000 (11:51 -0700)
committerGitHub <noreply@github.com>
Thu, 26 Jan 2017 18:51:28 +0000 (11:51 -0700)
* Use a prototype TextBlock to resolve theme resources on Windows

* Move textblock declaration to beginning of class

* Don't retain prototype TextBlock in memory

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs
Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43783.cs
new file mode 100644 (file)
index 0000000..99d4fca
--- /dev/null
@@ -0,0 +1,30 @@
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Bugzilla, 43783, "[WP8.1] Most Device Styles do not render correctly in Windows Phone 8.1 (RT) applications", PlatformAffected.WinPhone)]
+       public class Bugzilla43783 : TestContentPage
+       {
+               protected override void Init()
+               {
+                       Title = "Device";
+
+                       Content = new StackLayout
+                       {
+                               Children = {
+                                       new Label { Margin = new Thickness(10), Text = "The Labels for Body, Caption, List Item, List Item Detail, and No Style should not all look the same. If all of them look the same, this test has failed."},
+                                       new Label { Text = "Title style", Style = Device.Styles.TitleStyle },
+                                       new Label { Text = "Subtitle style", Style = Device.Styles.SubtitleStyle },
+                                       new Label { Text = "Body style", Style = Device.Styles.BodyStyle },
+                                       new Label { Text = "Caption style", Style = Device.Styles.CaptionStyle },
+                                       new Label { Text = "List item text style", Style = Device.Styles.ListItemTextStyle },
+                                       new Label { Text = "List item detail text style", Style = Device.Styles.ListItemDetailTextStyle },
+                                       new Label { Text = "No style" }
+                               }
+                       };
+               }
+
+       }
+}
\ No newline at end of file
index 68193dc..0ca65ac 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla43663.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla43867.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla43735.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Bugzilla43783.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44453.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44944.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44166.cs" />
index adbe7de..7b05159 100644 (file)
@@ -1,9 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Windows.UI.Text;
+using Windows.UI.Text;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
+using WStyle = Windows.UI.Xaml.Style;
 
 namespace Xamarin.Forms.Platform.WinRT
 {
@@ -12,89 +10,50 @@ namespace Xamarin.Forms.Platform.WinRT
        {
                public IResourceDictionary GetSystemResources()
                {
-                       var windowsResources = Windows.UI.Xaml.Application.Current.Resources;
-
-                       var resources = new ResourceDictionary ();
-                       resources[Device.Styles.TitleStyleKey] = GetStyle ("HeaderTextBlockStyle");
-                       resources[Device.Styles.SubtitleStyleKey] = GetStyle ("SubheaderTextBlockStyle");
-                       resources[Device.Styles.BodyStyleKey] = GetStyle ("BodyTextBlockStyle");
-                       resources[Device.Styles.CaptionStyleKey] = GetStyle ("BodyTextBlockStyle");
-                       resources[Device.Styles.ListItemTextStyleKey] = GetStyle ("ListViewItemTextBlockStyle");
-                       resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle ("ListViewItemContentTextBlockStyle");
-                       return resources;
+                       var prototype = new TextBlock();
+                       
+                       return new ResourceDictionary
+                       {
+                               [Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle", prototype),
+                               [Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle", prototype),
+                               [Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle", prototype),
+                               [Device.Styles.CaptionStyleKey] = GetStyle("BodyTextBlockStyle", prototype),
+                               [Device.Styles.ListItemTextStyleKey] = GetStyle("ListViewItemTextBlockStyle", prototype),
+                               [Device.Styles.ListItemDetailTextStyleKey] = GetStyle("ListViewItemContentTextBlockStyle", prototype)
+                       };
                }
 
-               Style GetStyle (object nativeKey)
+               static Style GetStyle(object nativeKey, TextBlock prototype)
                {
-                       var style = (Windows.UI.Xaml.Style) Windows.UI.Xaml.Application.Current.Resources[nativeKey];
-                       style = GetAncestorSetters(style);
+                       var style = (WStyle)Windows.UI.Xaml.Application.Current.Resources[nativeKey];
 
-                       var formsStyle = new Style (typeof (Label));
-                       foreach (var b in style.Setters) {
-                               var setter = b as Windows.UI.Xaml.Setter;
-                               if (setter == null)
-                                       continue;
+                       prototype.Style = style;
 
-                               // TODO: Need to implement a stealth pass-through for things we don't support
+                       var formsStyle = new Style(typeof(Label));
 
-                               if (setter.Property == TextBlock.FontSizeProperty)
-                                       formsStyle.Setters.Add (Label.FontSizeProperty, setter.Value);
-                               else if (setter.Property == TextBlock.FontFamilyProperty)
-                                       formsStyle.Setters.Add (Label.FontFamilyProperty, setter.Value);
-                               else if (setter.Property == TextBlock.FontWeightProperty)
-                                       formsStyle.Setters.Add (Label.FontAttributesProperty, ToAttributes (Convert.ToUInt16 (setter.Value)));
-                               else if (setter.Property == TextBlock.TextWrappingProperty)
-                                       formsStyle.Setters.Add (Label.LineBreakModeProperty, ToLineBreakMode ((TextWrapping) setter.Value));
-                       }
+                       formsStyle.Setters.Add(Label.FontSizeProperty, prototype.FontSize);
+                       formsStyle.Setters.Add(Label.FontFamilyProperty, prototype.FontFamily.Source);
+                       formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(prototype.FontWeight));
+                       formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode(prototype.TextWrapping));
 
                        return formsStyle;
                }
 
-               static Windows.UI.Xaml.Style GetAncestorSetters (Windows.UI.Xaml.Style value)
+               static FontAttributes ToAttributes(FontWeight fontWeight)
                {
-                       var style = new Windows.UI.Xaml.Style (value.TargetType)
-                       {
-                               BasedOn = value.BasedOn
-                       };
-                       foreach (var valSetter in value.Setters)
+                       if (fontWeight.Weight == FontWeights.Bold.Weight || fontWeight.Weight == FontWeights.SemiBold.Weight 
+                               || fontWeight.Weight == FontWeights.ExtraBold.Weight)
                        {
-                               style.Setters.Add(valSetter);
-                       }
-
-                       var ancestorStyles = new List<Windows.UI.Xaml.Style> ();
-
-                       Windows.UI.Xaml.Style currStyle = style;
-                       while (currStyle.BasedOn != null)
-                       {
-                               ancestorStyles.Add(currStyle.BasedOn);
-                               currStyle = currStyle.BasedOn;
+                               return FontAttributes.Bold;
                        }
 
-                       foreach (var styleParent in ancestorStyles)
-                       {
-                               foreach (var b in styleParent.Setters)
-                               {
-                                       var parentSetter = b as Windows.UI.Xaml.Setter;
-                                       if (parentSetter == null)
-                                               continue;
-
-                                       var derviedSetter = style.Setters
-                                               .OfType<Windows.UI.Xaml.Setter> ()
-                                               .FirstOrDefault (x => x.Property == parentSetter.Property);
-
-                                       //Ignore any ancestor setters which a child setter has already overridden
-                                       if (derviedSetter != null)
-                                               continue;
-                                       else
-                                               style.Setters.Add (parentSetter);
-                               }
-                       }
-                       return style;
+                       return FontAttributes.None;
                }
 
-               static LineBreakMode ToLineBreakMode (TextWrapping value)
+               static LineBreakMode ToLineBreakMode(TextWrapping value)
                {
-                       switch (value) {
+                       switch (value)
+                       {
                                case TextWrapping.Wrap:
                                        return LineBreakMode.CharacterWrap;
                                case TextWrapping.WrapWholeWords:
@@ -104,14 +63,5 @@ namespace Xamarin.Forms.Platform.WinRT
                                        return LineBreakMode.NoWrap;
                        }
                }
-
-               static FontAttributes ToAttributes (ushort uweight)
-               {
-                       if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight) {
-                               return FontAttributes.Bold;
-                       }
-
-                       return FontAttributes.None;
-               }
        }
 }
\ No newline at end of file
index 64041c0..c448567 100644 (file)
@@ -1,7 +1,7 @@
-using System;
-using Windows.UI.Text;
+using Windows.UI.Text;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
+using WStyle = Windows.UI.Xaml.Style;
 
 #if WINDOWS_UWP
 
@@ -15,60 +15,47 @@ namespace Xamarin.Forms.Platform.WinRT
        {
                public IResourceDictionary GetSystemResources()
                {
-                       Windows.UI.Xaml.ResourceDictionary windowsResources = Windows.UI.Xaml.Application.Current.Resources;
+                       var prototype = new TextBlock();
+
+                       return new ResourceDictionary
+                       {
+                               [Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle", prototype),
+                               [Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle", prototype),
+                               [Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle", prototype),
+                               [Device.Styles.CaptionStyleKey] = GetStyle("CaptionTextBlockStyle", prototype),
+                               [Device.Styles.ListItemDetailTextStyleKey] = GetStyle("BodyTextBlockStyle", prototype),
 
-                       var resources = new ResourceDictionary();
-                       resources[Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle");
-                       resources[Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle");
-                       resources[Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle");
-                       resources[Device.Styles.CaptionStyleKey] = GetStyle("CaptionTextBlockStyle");
 #if WINDOWS_UWP
-                       resources[Device.Styles.ListItemTextStyleKey] = GetStyle("BaseTextBlockStyle");
+                               [Device.Styles.ListItemTextStyleKey] = GetStyle("BaseTextBlockStyle", prototype),
 #else
-                       resources[Device.Styles.ListItemTextStyleKey] = GetStyle("TitleTextBlockStyle");
+                               [Device.Styles.ListItemTextStyleKey] = GetStyle("TitleTextBlockStyle", prototype),
 #endif
-                       resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle("BodyTextBlockStyle");
-                       return resources;
+                       };
                }
 
-               Style GetStyle(object nativeKey)
+               Style GetStyle(object nativeKey, TextBlock prototype)
                {
-                       var style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources[nativeKey];
+                       var style = (WStyle)Windows.UI.Xaml.Application.Current.Resources[nativeKey];
 
-                       var formsStyle = new Style(typeof(Label));
-                       foreach (SetterBase b in style.Setters)
-                       {
-                               var setter = b as Windows.UI.Xaml.Setter;
-                               if (setter == null)
-                                       continue;
+                       prototype.Style = style;
 
-                               // TODO: Need to implement a stealth pass-through for things we don't support
+                       var formsStyle = new Style(typeof(Label));
 
-                               try
-                               {
-                                       if (setter.Property == TextBlock.FontSizeProperty)
-                                               formsStyle.Setters.Add(Label.FontSizeProperty, setter.Value);
-                                       else if (setter.Property == TextBlock.FontFamilyProperty)
-                                               formsStyle.Setters.Add(Label.FontFamilyProperty, setter.Value);
-                                       else if (setter.Property == TextBlock.FontWeightProperty)
-                                               formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(Convert.ToUInt16(setter.Value)));
-                                       else if (setter.Property == TextBlock.TextWrappingProperty)
-                                               formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode((TextWrapping)setter.Value));
-                               }
-                               catch (NotImplementedException)
-                               {
-                                       // see https://bugzilla.xamarin.com/show_bug.cgi?id=33135
-                                       // WinRT implementation of Windows.UI.Xaml.Setter.get_Value is not implemented.
-                               }
-                       }
+                       formsStyle.Setters.Add(Label.FontSizeProperty, prototype.FontSize);
+                       formsStyle.Setters.Add(Label.FontFamilyProperty, prototype.FontFamily.Source);
+                       formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(prototype.FontWeight));
+                       formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode(prototype.TextWrapping));
 
                        return formsStyle;
                }
 
-               static FontAttributes ToAttributes(ushort uweight)
+               static FontAttributes ToAttributes(FontWeight fontWeight)
                {
-                       if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight)
+                       if (fontWeight.Weight == FontWeights.Bold.Weight || fontWeight.Weight == FontWeights.SemiBold.Weight 
+                               || fontWeight.Weight == FontWeights.ExtraBold.Weight)
+                       {
                                return FontAttributes.Bold;
+                       }
 
                        return FontAttributes.None;
                }