自定义控件,如StackLayout和Xamarin.Forms

时间:2016-06-07 05:32:29

标签: xaml xamarin custom-controls xamarin.forms

我只想用Xamarin.Forms创建一个自定义控件。此自定义控件应采用xaml中的数组/视图列表(例如,Stacklayout)。

我的XAML看起来像这样:

<controls:MyLayout>
    <ContentView BackgroundColor="Green">
        <Label Text="Test 1" />
    </ContentView>

    <ContentView BackgroundColor="Red">
        <Label Text="Test 1" />
    </ContentView>
</controls:MyLayout>

MyLayout的课程:

[ContentProperty("Children")]
public class MyLayout: ScrollView, IViewContainer<View>
{
     public IList<View> Children { get; set; }

    // And some more properties and methods ...
}

但是当我编译并在我的Android手机上运行它时,我收到以下错误:

  

调用目标抛出了异常。 ---&GT;   Xamarin.Forms.Xaml.XamlParseException:位置29:8。无法分配   属性“Children”:“Xamarin.Forms.ContentView”之间的类型不匹配   和“System.Collections.Generic.IList`1 [Xamarin.Forms.View]”

我该如何解决这个问题?我错过了什么?

3 个答案:

答案 0 :(得分:0)

这个问题听起来像是一个已知问题,并且非常古老...

面对这一点,我使用了没有泛型的简单IList,它适用于StackLayout

在您的情况下,我认为您应该首先更改您的基类,因为ScrollView已经具有[ContentProperty("Content")]属性,我认为ContentView应当保留其优先级。 / p>

另一种方法是让您成为基础类,使用IList而不使用泛型,并且在需要的地方使用Children as List<View>if(Children is List<View> l)...

AND 并且不要忘记在XAML中明确指定<xxx:MyLayout.ContentView>,只要它不再是 ContentProperty

答案 1 :(得分:0)

您的财产孩子必须只能获得访问者。我记得这也是一个面临的问题。并且该列表也必须初始化。

[ContentProperty("Children")]
public class MyLayout: ScrollView, IViewContainer<View>
{
     public IList<View> Children { get; } = new List<View>();

    // And some more properties and methods ...
}

我宁愿这样

[ContentProperty(nameof(Children))]
public class MyLayout: ScrollView, IViewContainer<View>
{
     private List<View> _children;
     public IList<View> Children => _children;

     public MyLayout()
     {
         _children = new List<View>();
     }
    // And some more properties and methods ...
}

或者甚至使用ObservableCollection <>代替简单的List <>。 ObservableCollection可以帮助您观察集合何时发生更改,它可以帮助您何时布局的内容子级在布局中添加或删除

答案 2 :(得分:-1)

您需要将物品放入容器中,如:

                                   

    <ContentView BackgroundColor="Red">
        <Label Text="Test 1" />
    </ContentView>
</x:Array>

但我认为这不是一个好方法。您可以像下面一样为View集合创建一个类,并在代码中使用它,这样您就可以观察在运行时是否添加了某些内容:

public class ViewCollection : ObservableCollection<View>
{

}


<controls:MyLayout>
    <local:ViewCollection Type="{x:Type View}">
        <ContentView BackgroundColor="Green">
            <Label Text="Test 1" />
        </ContentView>

        <ContentView BackgroundColor="Red">
            <Label Text="Test 1" />
        </ContentView>
    </local:ViewCollection>
</controls:MyLayout>

您还需要将Children属性类型更改为ViewCollection