如何在自定义控件上正确显示属性?

时间:2015-11-09 16:54:47

标签: c# wpf xaml xamarin xamarin.forms

我正在尝试在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>部分拿出来,我会收到错误:

  

序列不是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>

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

2 个答案:

答案 0 :(得分:1)

来自What is the worst gotcha in WPF?

  

3)如果XAML将属性识别为集合属性,则属性的类型必须实现IList,而不是IList<T>

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

如果这不能解决您的问题,请改进您的问题。提供可靠地再现问题的a good, minimal, complete code example,以便更清楚情况是什么。

您可能也对How Can I Nest Custom XAML Elements?感兴趣,它展示了如何将属性声明为XAML中子元素的默认集合。

答案 1 :(得分:0)

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

首先,我必须在IList上实施ExtendedMap,以便我可以在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;
    }
}