【问题标题】:How do I correctly Expose a property on a custom control?如何正确公开自定义控件上的属性?
【发布时间】:2016-02-10 09:29:23
【问题描述】:

我正在尝试在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>

如果我取出 &lt;x:Array&gt; 部分,我会收到错误:

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

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

【问题讨论】:

标签: c# wpf xaml xamarin xamarin.forms


【解决方案1】:

来自What is the worst gotcha in WPF?

3) 如果属性要被 XAML 识别为集合属性,则属性的类型必须实现 IList,而不是 IList&lt;T&gt;

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

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

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

【讨论】:

  • 你的第一点是正确的。我必须实现IList 而不是IList&lt;T&gt;。我稍后会发布我的实际解决方案。
【解决方案2】:

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

首先我必须在我的ExtendedMap 上实现IList,这样我就可以在不使用Array 的情况下设置Xaml 中的项目列表

最终的解决方案是这样的:

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;
    }
}

【讨论】:

  • 我假设您选择在类本身中实现IList,而不是在声明中添加[ContentProperty("StaticPins")],因为前一种方法允许您保留属性类型上的通用IList&lt;Pin&gt;而后者不会。如果这是真的,您可能需要在上面的答案中添加评论,以便让未来的读者明白这一点,以便他们更好地理解这两个选项之间的权衡。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-11
  • 2010-11-25
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 2011-10-20
相关资源
最近更新 更多