忽略绑定初始化
Posted
技术标签:
【中文标题】忽略绑定初始化【英文标题】:Ignore the Binding initialization 【发布时间】:2017-01-22 08:24:56 【问题描述】:最初的问题来自personal project about the polyline of the Xamarin.Forms.Map,其中初始化是通过来自 XAML 部分的绑定实现的。
举个例子说明一下:
我有一个对象 CustomMap.cs,它继承自 Xamarin.Forms.Map
(此文件位于 PCL 部分 -> CustomControl/CustomMap.cs)
public class CustomMap : Map, INotifyPropertyChanged
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(List<string>), typeof(CustomMap), null);
public List<string> PolylineAddressPoints
get return (List<string>)GetValue(PolylineAddressPointsProperty);
set
SetValue(PolylineAddressPointsProperty, value);
this.GeneratePolylineCoordinatesInner();
// ...
如您所见,我有一个可绑定属性与评估器,而 XAML 似乎没有使用此评估器..
所以页面的 MainPge.xaml 部分(调用该控件的位置)如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:MapPolylineProject.CustomControl;assembly=MapPolylineProject"
x:Class="MapPolylineProject.Page.MainPage">
<ContentPage.Content>
<control:CustomMap x:Name="MapTest" PolylineAddressPoints="Binding AddressPointList"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
</ContentPage>
MainPge.xaml.cs 部分:
public partial class MainPage : ContentPage
public List<string> AddressPointList get; set;
public MainPage()
base.BindingContext = this;
AddressPointList = new List<string>()
"72230 Ruaudin, France",
"72100 Le Mans, France",
"77500 Chelles, France"
;
InitializeComponent();
//MapTest.PolylineAddressPoints = AddressPointList;
所以,如果我从对象实例编辑PolylineAddressPoints
,一切都很好(如果注释部分没有被注释..),但是如果我从 XAML 中初始化值(从InitializeComponent();
),它不起作用,Set
,CustomMap.PolylineAddressPoints
中的SetValue
没有被调用..
然后我在网上搜索了它并获得了一些关于 依赖属性? 或类似的东西。所以我尝试了一些解决方案,但是,来自 WPF,所以一些方法,比如DependencyProperty.Register();
。所以是的,我找不到解决问题的方法..
我也想到了一些事情,如果DependencyProperty.Register();
将存在于 Xamarin.Forms 中,那么这意味着我必须为每个值都这样做吗?因为,如果每个值都必须由 XAML 绑定逻辑 设置,那将无法正常工作,我必须注册每个值,不是吗?
如果我不清楚,我很抱歉,但我对这个问题很迷茫。请不要犹豫,询问更多细节,提前谢谢!
最后,最初的问题是我试图从 XAML 中设置对象/控件的值。通过绑定执行此操作不起作用,似乎它被忽略了。但是,如果我执行以下操作,它确实有效:
MapTest.PolylineAddressPoints = AddressPointList;
【问题讨论】:
【参考方案1】:这里有多个问题:
为什么在使用 Xaml 时从不调用属性设置器? 我是否正确定义了我的 BindableProperty ? 为什么我的绑定失败了?让我以不同的顺序回答它们。
我是否正确定义了我的 BindableProperty ?
BindableProperty 声明是正确的,但可以通过使用IList<string>
来改进:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null);
但是属性访问器是错误的,应该只包含这个:
public IList<string> PolylineAddressPoints
get return (IList<string>)GetValue(PolylineAddressPointsProperty);
set SetValue(PolylineAddressPointsProperty, value);
我会在回答下一个问题时告诉你原因。但是您想在属性更改时调用方法。为此,您必须将propertyChanged
委托引用到CreateBindableProperty
,如下所示:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null,
propertyChanged: OnPolyLineAddressPointsPropertyChanged);
您也必须声明该方法:
static void OnPolyLineAddressPointsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
((CustomMap)bindable).OnPolyLineAddressPointsPropertyChanged((IList<string>)oldValue, (IList<string>)newValue);
void OnPolyLineAddressPointsPropertyChanged(IList<string> oldValue, IList<string> newValue)
GeneratePolylineCoordinatesInner();
为什么在使用 Xaml 时从不调用属性设置器?
属性和属性访问器仅在通过代码访问属性时才被调用。 C#
代码。
当使用 Xaml 的 BindablePrperty 后备存储设置属性时,会绕过属性访问器并直接使用 SetValue()
。
从代码或 Xaml 定义 Binding
时,再次绕过属性访问器,并在需要修改属性时使用 SetValue()
。而当SetValue()
被调用时,propertyChanged
委托在属性改变之后被执行(这里要完整,propertyChanging
在属性改变之前被调用)。
如果可绑定属性仅由 xaml 使用,或者在 Binding 上下文中使用,您可能想知道为什么还要费心定义该属性。好吧,我说属性访问器没有被调用,但是它们在 Xaml 和 XamlC 的上下文中使用:
可以在属性上定义[TypeConverter]
属性,并将被使用
启用XamlC
,属性签名可用于在编译时推断BindableProperty
的Type
。
因此,始终为公共 BindableProperties 声明属性访问器是一个好习惯。总是。
为什么我的绑定失败了?
由于您将CustomMap
用作View
和ViewModel
(我不会告诉Mvvm Police),因此在您的构造函数中这样做就足够了:
BindingContext = this; //no need to prefix it with base.
正如你已经在做的那样,一旦你按照我之前解释的方式修改了 BindableProperty
声明,你的 Binding
应该可以工作了。
【讨论】:
您好,感谢您的解释,这是一个非常好的答案,同时也解决了我的问题!再次感谢:)以上是关于忽略绑定初始化的主要内容,如果未能解决你的问题,请参考以下文章