如何在自定义控件上正确公开 属性?

How do I correctly Expose a property on a custom control?

我正在尝试在 Xamarin.Forms 中创建自定义控件并正确公开 属性。我确信同样的原则适用于 WPF

我的控制

public class ExtendedMap : Map
{
    public ExtendedMap()
    {

    }

    private IList<Pin> _staticPins;
    public IList<Pin> StaticPins
    {
        get { return _staticPins; }
        set { _staticPins = value;}
    }
}

Xaml中,我目前是这样使用它的:

<custom:ExtendedMap x:Name="map" Grid.Row="2" HorizontalOptions="Fill" VerticalOptions="Fill" IsVisible="{Binding CustomerSearchControlViewModel.MapIsDisplayed}">
  <custom:ExtendedMap.StaticPins>
    <x:Array Type="{x:Type maps:Pin}">
      <maps:Pin Label="Hello" Address="{Binding CustomerSearchControlViewModel.SelectedCustomer.Address, Converter={StaticResource AddressToStringConverter}" Position="{Binding CustomerSearchControlViewModel.SelectedCustomer.Position}" Type="Place"/>
    </x:Array>
  </custom:ExtendedMap.StaticPins>
</custom:ExtendedMap>

如果我取出 <x:Array> 部分,我会得到一个错误:

Sequence is not IEnumerable

但我想像这样使用它:

<custom:ExtendedMap.StaticPins>
      <maps:Pin Label="Hello" Address="{Binding CustomerSearchControlViewModel.SelectedCustomer.Address, Converter={StaticResource AddressToStringConverter}" Position="{Binding CustomerSearchControlViewModel.SelectedCustomer.Position}" Type="Place"/>
 </custom:ExtendedMap.StaticPins>

这可能吗?正确的做法是什么?

来自What is the worst gotcha in WPF?

3) Property's type must implement IList, not IList<T>, if the property is to be recognized by XAML as a collection property.

更一般地说,不幸的是,XAML 和泛型不能很好地协同工作。

如果这不能解决您的问题,请改进您的问题。提供可靠重现问题的a good, minimal, complete code example,这样更清楚是什么场景。

您可能还对 How Can I Nest Custom XAML Elements? 感兴趣,它展示了如何将 属性 声明为 XAML.

中子元素的默认集合

感谢@Peter Duniho 的回答,它迫使我朝着正确的方向前进。这是他提到的几点的组合。

首先,我必须在 ExtendedMap 上实现 IList,这样我就可以在 Xaml 中设置项目列表,而无需使用 Array

最终的解决方案如下所示:

public class ExtendedMap : Map : IList
{
    public ExtendedMap()
    {

    }

    private IList<Pin> _staticPins = new List<Pin>();
    public IList<Pin> StaticPins
    {
        get { return _staticPins; }
        set { _staticPins = value;}
    }

    //..IList Implementations

    Public int Add(object item)
    {
       var pin = (Pin)item;
       StaticPins.Add(pin);
       return 1;
    }
}