所以我必须这样做的方式非常复杂,所以请仔细听。
我发现这里真正的问题是我需要“主题化”我的 Xamarin.Forms 应用程序。
这就是我所做的。
先做了一个abstract Theme类:
public abstract class Theme
{
public Dictionary<string, Color> Colours { get; set; } = new Dictionary<string, Color>();
protected void DictionaryThemes(Type type)
{
var properties = type.GetRuntimeProperties();
foreach (PropertyInfo propInfo in properties)
{
if (propInfo.PropertyType == typeof(Color))
{
var key = propInfo.Name;
var value = propInfo.GetValue(this);
Colours.Add(key, (Color)value);
}
}
}
public abstract Color TitleColour { get; }
}
用一种很好的方法使用反射来填充我的Resources的字典
然后我用我的实际主题扩展了这个类:
public class MyTheme : Theme
{
public MyTheme()
{
DictionaryThemes(typeof(MyTheme));
}
//Slate
public override Color TitleColour { get; } = Color.FromHex("#00ff00");
}
还和我在一起吗?不错……
然后我不得不将此主题加载到我的Application Resources 中,并将其与我的其他应用程序资源合并。我必须将MyTheme 资源与另一个Resources 分开,以便稍后在我的主Resources 文件中使用它。
让我告诉你,这是我的CurrentTheme资源文件:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:styling="clr-MyApp.Styling;assembly=MyApp"
x:Class="MyApp.Styling.CurrentTheme">
<ContentPage.Resources>
<ResourceDictionary>
<styling:MyTheme x:Key="CurrentTheme"/>
</ResourceDictionary>
我必须将它作为页面的一部分,因为 Xamarin.Forms 有 Sealed ResourceDictionary 类 (see here) 意味着你不能扩展它并创建自己的......耻辱。反正我跑题了。
然后我将我的应用程序资源设置为CurrentTheme,如下所示:
var currentTheme = new CurrentTheme();
Xamarin.Forms.Application.Current.Resources = currentTheme.Resources;
然后我可以从我的主要Resource 文件中合并其他样式,在本例中称为Styles:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:styling="clr-MyApp.Styling;assembly=MyApp"
x:Class="MyApp.Styling.Styles">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="TitleStyle" TargetType="Label">
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="FontSize" Value="30" />
<Setter Property="TextColor" Value="{styling:Colour TitleColour}" />
</Style>
</ResourceDictionary>
我将它合并到我的主要应用程序资源中,如下所示:
var styles = new Styles();
foreach (var item in styles.Resources)
{
Application.Current.Resources.Add(item.Key,item.Value);
}
现在您可以看到 Styles 类中的一个 setter 属性如下所示:
你是说那个值是什么意思?
这是拼图的最后一块。一种扩展方法,允许您像上面一样定义xaml。
首先是ColourExtension 类:
// You exclude the 'Extension' suffix when using in Xaml markup
[ContentProperty("Text")]
public class ColourExtension : IMarkupExtension
{
public string Text { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
throw new Exception("No Colour Key Provided");
return StylingLookup.GetColour(Text);
}
}
最后是StylingLookup 类:
public static class StylingLookup
{
public static Color GetColour(string key)
{
var currentTheme = (Application.Current.Resources["CurrentTheme"] as Theme);
return currentTheme.Colours[key];
}
}
现在这一切都说得通了,为什么我们必须将 CurrentTheme 与主要的 Styles 资源分开。因为线:
var currentTheme = (Application.Current.Resources["CurrentTheme"] as Theme);
如果有人有更好的样式设计模式我很想听听的应用程序