xaml - 忽略绑定(bind)初始化

标签 xaml xamarin binding initialization xamarin.forms

最初的问题来自 personal project about the polyline of the Xamarin.Forms.Map其中初始化是通过来自 XAML 部分的绑定(bind)实现的。

让我举个例子说清楚:

我有一个对象 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();
        }
    }   
    // ...
}

如您所见,我有一个可绑定(bind)的属性与评估器,而 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(); ),它不起作用, SetValue ,在 Set {} , 的 CustomMap.PolylineAddressPoints ,不叫..

然后我在网上搜索了一下,得到了一些关于 的信息。依赖属性? 或类似的东西。所以我尝试了一些解决方案,但是,来自 WPF,所以一些方法,例如 DependencyProperty.Register(); .所以是的,我找不到解决问题的方法..

我也想过一些事情,如果 DependencyProperty.Register();将存在于 Xamarin.Forms ,那么这意味着我必须为每个值都这样做吗?因为,如果每个值都必须由 XAML 绑定(bind)逻辑设置,那么它将不起作用,我必须注册每个值,不是吗?

如果我不清楚,我很抱歉,但我对这个问题很迷茫..请不要犹豫,询问更多细节,提前谢谢!

最后,最初的问题是我试图从 XAML 设置对象/控件的值。通过绑定(bind)执行此操作不起作用,似乎它被忽略了。但是,如果我执行以下操作,它确实有效:
MapTest.PolylineAddressPoints = AddressPointList;  

最佳答案

这里面有多个问题:

  • 为什么使用 Xaml 时从不调用属性 setter ?
  • 我是否正确定义了我的 BindableProperty ?
  • 为什么我的绑定(bind)失败?

  • 让我以不同的顺序回答它们。

    我是否正确定义了我的 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委托(delegate)给 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 时从不调用属性 setter ?

    属性和属性访问器仅在通过代码访问属性时才被调用。 C#代码。

    当使用 Xaml 中的 BindablePrperty 后备存储设置属性时,会绕过属性访问器和 SetValue()是直接使用的。

    定义 Binding 时,无论是来自代码还是来自 Xaml,都会再次绕过属性访问器和 SetValue()在需要修改属性时使用。当SetValue()被调用,propertyChanged委托(delegate)在属性更改后执行(此处要完整,propertyChanging 在属性更改之前调用)。

    如果可绑定(bind)属性仅由 xaml 使用,或者在 Binding 的上下文中使用,您可能想知道为什么还要费心定义该属性。好吧,我说没有调用属性访问器,但它们在 Xaml 和 XamlC 的上下文中使用:
  • 一个 [TypeConverter]可以在属性上定义属性,并将使用
  • XamlC on,属性签名可用于在编译时推断 TypeBindableProperty .

  • 因此,始终为公共(public) BindableProperties 声明属性访问器是一个好习惯。总是。

    为什么我的绑定(bind)失败?

    当您使用 CustomMap作为ViewViewModel (我不会告诉 Mvvm Police),在你的构造函数中这样做就足够了:

    BindingContext = this; //no need to prefix it with base.
    

    正如你已经在做的那样,你的 Binding修改 BindableProperty 后应该可以工作以我之前解释的方式声明。

    关于xaml - 忽略绑定(bind)初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39491978/

    相关文章:

    wpf - 如何在 Windows 8 商店应用程序中访问 Parent 的 DataContext

    android - SQLite 向表中添加一个列表

    xamarin - 如何使用 VisualStudio 2015 Community 在 Xamarin Starter Edition 中制作 Android UI?

    wpf - 在 WPF 中获取动态资源绑定(bind)

    spring - 如何从绑定(bind)结果中出现错误的属性文件获取本地化消息?

    xaml - 图像正在 UWP 应用程序中缓存

    wpf - 如何使 WPF ListView 项目水平重复,就像水平滚动条一样?

    Android ScrollView /背景图片/Xamarin

    c - 在运行时或编译/链接时绑定(bind)模块的接口(interface)需求,哪个更好?

    c# - 未找到用于绑定(bind)配方的数据上下文