如何在自己的ContentView(自定义控件)中使用Xamarin.Forms.Setter类?

时间:2019-01-25 13:54:44

标签: c# xaml xamarin xamarin.forms

我正在创建一个名为ContentView的{​​{1}}自定义控件。基本上,这是一个可以处理两个AutoAdaptingView(FirstContent和SecondContent)的网格,并且它将根据方向,屏幕高度等自动将两个View放在两行或两列中。 现在,我想创建两个附加的View,它们分别是PortraitSetters和LandscapeSetters,它们分别是BindableProperty,以便此类的使用者可以使用XAML来声明Horizo​​ntalOptions,RequestedHeight和其他任何相关属性的变体。 List<Setter>的列表。方向更改时,将扫描该列表,并将使用“反射”设置所有需要设置的属性。 问题是,如果我使用这样的列表,它将无法编译,因为它无法从Setter转换为string

这是我的BindableProperty声明:

BindableProperty

下面是如何使用它的示例:

        //
        public static readonly BindableProperty PortraitSettersProperty = BindableProperty.CreateAttached(
            "PortraitSetters",
            typeof(List<Setter>),
            typeof(AutoAdaptingView),
            null
        );

        public static List<Setter> GetPortraitSetters(BindableObject target)
        {
            return (List<Setter>)(target as View).GetValue(PortraitSettersProperty);
        }

        public static void SetPortraitSetters(BindableObject target, List<Setter> value)
        {
            (target as View).SetValue(PortraitSettersProperty, value);
        }

        //
        public static readonly BindableProperty LandscapeSettersProperty = BindableProperty.CreateAttached(
            "LandscapeSetters",
            typeof(List<Setter>),
            typeof(AutoAdaptingView),
            null
        );

        public static List<Setter> GetLandscapeSetters(BindableObject target)
        {
            return (List<Setter>)(target as View).GetValue(LandscapeSettersProperty);
        }

        public static void SetLandscapeSetters(BindableObject target, List<Setter> value)
        {
            (target as View).SetValue(LandscapeSettersProperty, value);
        }

这里是问题:

<ctrl:AutoAdaptingView>
    <ctrl:AutoAdaptingView.FirstContent>
        <StackLayout Orientation="Vertical"
                     Spacing="16">

            <ctrl:AutoAdaptingView.PortraitSetters>
                <Setter Property="HorizontalOptions" Value="Center"/>
                <Setter Property="VerticalOptions" Value="Start"/>
                <Setter Property="Margin" Value="16, 100, 16, 16"/>
            </ctrl:AutoAdaptingView.PortraitSetters>

            <ctrl:AutoAdaptingView.LandscapeSetters>
                <Setter Property="HorizontalOptions" Value="Center"/>
                <Setter Property="VerticalOptions" Value="Center"/>
                <Setter Property="Margin" Value="16"/>
            </ctrl:AutoAdaptingView.LandscapeSetters>

            <!-- actual content here -->

很明显,我不希望XAML神奇地理解Cannot convert "HorizontalOptions" into Xamarin.Forms.BindableProperty 字段引用Property BindableProperty,但与StackLayout类具有{{1 }}属性,允许它自动将属性名称字符串转换为实际的Style对象,应该有一种方法可以允许我实现相同的对象。

我考虑过的解决方案是创建自己的Setter类,而不是TargetType对象,它仅使用一个属性名称(因为这是我在实现中实际需要的名称),但随后不会我需要创建一个转换器来转换值(即BindablePropertyBindableProperty)吗?

最简单的解决方案是使用事件,供消费者在后面的代码中处理,但这会浪费代码-资源分离的优势。

1 个答案:

答案 0 :(得分:1)

您可以在App.xaml(全局样式)中定义样式

<Style x:Key="portraitStyle" TargetType="custom:LabelEntry">
   <Setter Property="HorizontalOptions" Value="Center"/>
            <Setter Property="VerticalOptions" Value="Start"/>
            <Setter Property="Margin" Value="16, 100, 16, 16"/>
</Style>

,然后在您的视图绑定中

Style="{Binding YourProperty , Converter={ StaticResource ConvertStyleKey }}"

带有用于以下目的的转换器

public class ConvertStyle : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        valueType = (YourModel)value
        if (valueType.YourProperty)
        {
            return Application.Current.Resources["portraitStyle"] as Style;
        }
        else
        {
            //other style
        }
    }
}