【问题标题】:Custom control like StackLayout with Xamarin.Forms自定义控件,如 StackLayout 和 Xamarin.Forms
【发布时间】:2016-06-07 05:32:28
【问题描述】:

我只想用 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 手机上运行它时,我收到以下错误:

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

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

【问题讨论】:

  • 不,这不是问题所在。使用“ContentView”时,我遇到了同样的错误:“Xamarin.Forms.ContentView”和“System.Collections.Generic.IList`1[Xamarin.Forms.ContentView]”之间的类型不匹配
  • 您可以参考Xamarin.Forms 源来创建您的控件,因为它是开源的。你可以在github.com/xamarin/Xamarin.Forms找到代码

标签: xaml xamarin custom-controls xamarin.forms


【解决方案1】:

这个问题听起来像是一个已知问题,而且已经很老了......

面对这个问题,我使用了没有泛型类型的简单IList,它适用于StackLayout

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

另一种方法是保留基类,使用不带泛型的IList,在需要的任何地方使用Children as List&lt;View&gt;if(Children is List&lt;View&gt; l)...

AND 不要忘记在 XAML 中明确指定 &lt;xxx:MyLayout.ContentView&gt;,只要它不再是 ContentProperty

【讨论】:

    【解决方案2】:

    您的属性 Children 必须只有 get 访问器。我记得这也是一个面临的问题。而且这个列表也必须被初始化。

    [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 可以帮助您观察集合何时发生变化,它可以帮助您何时从布局中添加或删除布局的内容子项

    【讨论】:

      【解决方案3】:

      您需要将项目放入容器中,例如:

          <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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-20
        • 1970-01-01
        • 2018-02-17
        • 1970-01-01
        • 2020-08-31
        • 2018-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多