【问题标题】:Is there any way to separate the styling from my XAML in Xamarin.Forms有没有办法在 Xamarin.Forms 中将样式与我的 XAML 分开
【发布时间】:2014-06-26 08:26:48
【问题描述】:

我在带有 XAML 页面的 PCL 中使用 Xamarin.Forms。我发现设置控件样式的唯一方法是使用内联语法。

<Button Text="Inquiry" TextColor="Blue" />

我更喜欢使用这样的结构:

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Blue" />
    </Style>
</Page.Resources>

(http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh465381.aspx)

但是,尚不支持 Style 元素。 有没有人成功地将布局与内容分开?

仅供参考:我还在 Xamarin 论坛中发布了这个问题,所以任何通过 google 访问这里的人可能还想查看此页面:http://forums.xamarin.com/discussion/19287/styling-of-xamarin-xaml#latest

【问题讨论】:

    标签: c# xaml xamarin xamarin.forms


    【解决方案1】:

    风格不是那么困难[需要引用]。您可以实现自己的,就像我刚刚为回答此问题所做的那样。

    Xaml 如下所示:

    <ContentPage
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:local="clr-namespace:YourNS;assembly=YourAssembly">
        <ContentPage.Resources>
            <ResourceDictionary>
                <local:Style x:Key="buttonStyle">
                    <local:Setter Property="BorderWidth" Value="5"/>
                </local:Style>
            </ResourceDictionary>
        </ContentPage.Resources>
    
        <Button Text="Foo" local:Style.Style="{StaticResource buttonStyle}" x:Name="button"/>
    </ContentPage>
    

    支持代码如下所示:

    namespace YourNS
    {
    
        public class Setter {
            public string Property { get; set; }
            public string Value { get; set; }
        }
    
        [ContentProperty ("Children")]
        public class Style
        {
            public Style ()
            {
                Children = new List<Setter> ();
            }
    
            public IList<Setter> Children { get; private set; }
    
            public static readonly BindableProperty StyleProperty = 
                BindableProperty.CreateAttached<Style, Style> (bindable => GetStyle (bindable), default(Style), 
                    propertyChanged: (bindable, oldvalue, newvalue)=>{
                        foreach (var setter in newvalue.Children) {
                            var pinfo = bindable.GetType().GetRuntimeProperty (setter.Property);
                            pinfo.SetMethod.Invoke (bindable,new [] {Convert.ChangeType (setter.Value, pinfo.PropertyType.GetTypeInfo())});
                        }
    
                    });
    
            public static Style GetStyle (BindableObject bindable)
            {
                return (Style)bindable.GetValue (StyleProperty);
            }
    
            public static void SetStyle (BindableObject bindable, Style value)
            {
                bindable.SetValue (StyleProperty, value);
            }
        }
    }
    

    显然,执行分配的代码非常简单,您可能需要根据需要对其进行调整(支持枚举等),但它适用于这种简单的情况。

    我相信它会有所帮助。

    【讨论】:

    • 看起来是朝着正确方向迈出的一大步。我在这里仍然想念的一件事是我仍然必须为每个控件分配样式。您对如何实现“TargetType”属性有任何想法吗?
    • TargetType 并不是使样式隐含在 WPF/SL 中的原因。没有 x:Key 是。您可以非常轻松地实现 TargetType,这将添加一个检查以避免在不存在的元素上查找属性,但是您现在找不到为 Xamarin.Forms 控件设置隐式样式的方法,除非您创建每种类型都有一个子类。
    • 使用类型转换器设置 LayoutOptions 和其他属性的样式,这对我有用:var converterInfo = pInfo.PropertyType.GetCustomAttribute&lt;TypeConverterAttribute&gt;(); if (converterInfo != null) { var converterType = Type.GetType(converterInfo.ConverterTypeName); var conv = (TypeConverter)Activator.CreateInstance(converterType); return conv.ConvertFrom(value); }
    • 我使用上述代码“错误 CS0029: 无法隐式转换类型 NS.LeftMenu.Style' to TPropertyType' (CS0029) (NS)”时遇到此错误
    • @NiravMehta 命名空间冲突。要么将 Style 重命名为其他名称,要么为类型提供完整的命名空间
    【解决方案2】:

    样式支持现已推出:

    <ContentPage.Resources>
       <ResourceDictionary>
    
      <Style TargetType="Label">
        <Setter Property="HorizontalOptions" Value="LayoutOptions.Center" />
        <Setter Property="VerticalOptions" Value="LayoutOptions.Center" />
        <Setter Property="FontSize" Value="48" />
        <Setter Property="FontAttributes" Value="Bold, Italic" />
        <Setter Property="Opacity" Value=".5" />
        <Setter Property="TextColor" Value="Black" />
        <Setter Property="Text" Value="Copied" />
        <Setter Property="IsVisible" Value="False" />
      </Style>
    
      </ResourceDictionary>
    </ContentPage.Resources>
    

    【讨论】:

    • 我在不使用 XAML 的情况下创建布局。如何仅使用代码来使用这种风格?
    【解决方案3】:

    从 Xamarin.Forms 1.3 中,您可以获得更多样式选项。

    Xamarin.Forms 1.3 Technology Preview

    • 支持 XAML 和代码中的样式
    • 通过 Style.BaseResourceKey 允许样式基于 DynamicResources
    • 通过 Device.Styles 添加平台特定样式(支持 iOS 动态类型)

    【讨论】:

      【解决方案4】:

      我能够创建更接近我在 WPF/Silverlight 中更习惯的 ResourceDictionary 的代码,并将其从实际页面(视图)中删除

      1. 我创建了一个新的 xaml 文件,而不是只有 App.cs。App.xaml 及其随附的 App.xaml.cs 代码隐藏。我将 App.cs 中的内容放入 App.xaml.cs。

        public partial class App : Application
        {
            public App()
            {
               var _mainView = new MainView();
               var _navPage = new NavigationPage(_mainView);
               MainPage = _navPage;
            }
        
           //.. the methods below are currently empty on mine, 
           //still figuring out some of the front end ..
           protected override void OnStart(){ }
           protected override void OnSleep(){ }
           protected override void OnResume(){ }    
        

        }

      2. 这允许我在 App.xaml 中声明我可以在其他视图上使用的应用程序资源:

            <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
                <Setter Property="TextColor" Value="Blue"/>
                <!-- note: I tried Foreground and got errors, but once I 
                     used TextColor as the property, it ran fine and the 
                     text of the button I had changed color to what I expected -->
                <Setter Property="BackgroundColor" Value="White"/>
                <!-- note: I tried Background and got errors, but once I 
                     used BackgroundColor as the property, it ran fine and the 
                     background of the button I had changed color -->
            </Style>
        
        </ResourceDictionary>
        

      然后我可以通过使用 StaticResource 在我的页面上使用该样式

      <Button Text="Inquiry" Style="{StaticResource buttonStyle}"/>
      

      可能有几十种方法,甚至可能更好 - 但这帮助我将所有样式保存在一个位置 (App.xaml)

      附注我不知道为什么它没有格式化代码隐藏示例,我尝试了几次但希望你仍然理解它。

      【讨论】:

      • 是否可以引用上面代码中创建的buttonStyle来为example.cs文件中的按钮设置样式。
      【解决方案5】:

      作为 Silverlight 开发人员,我正在考虑 Xamarin Forms 的这个问题。

      一种可选方法是在 XAML 或代码中创建自己的控件(Xamarin 术语中的“视图”),并在构建界面时使用这些控件。

      【讨论】:

        猜你喜欢
        • 2018-08-06
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 2015-01-03
        • 2017-06-29
        • 1970-01-01
        • 2011-04-15
        • 2016-05-29
        相关资源
        最近更新 更多