如何在自定义控件上正确公开 属性?
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;
}
}
我正在尝试在 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
, notIList<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;
}
}