在Xamarin.Forms中绑定自定义视图

Mik*_*keW 13 c# xaml xamarin xamarin.forms

我在将Xamarin表单中的自定义视图中的数据绑定到包含页面的视图模型时遇到问题.

我的自定义视图非常简单,一对代表键值对的标签:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="KeyValueView">
    <Grid VerticalOptions="Start">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Label x:Name="KeyLabel" Text="{Binding Key}"  Grid.Column="0" HorizontalOptions="Start" />
        <Label x:Name="ValueLabel" Text="{Binding Value}" Grid.Column="1" HorizontalOptions="EndAndExpand" />
    </Grid>
</ContentView>
Run Code Online (Sandbox Code Playgroud)

后面的代码:

public partial class KeyValueView : ContentView
{
    public KeyValueView()
    {
        InitializeComponent();
        this.VerticalOptions = LayoutOptions.Start;
        this.BindingContext = this;
    }

    public static readonly BindableProperty ValueProperty =
                BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string));

    public string Value
    {
        get {return (string)GetValue(ValueProperty);}
        set {SetValue(ValueProperty, value);}
    }

    public static readonly BindableProperty KeyProperty =
        BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string));

    public string Key
    {
        get {return (string)GetValue(KeyProperty);}
        set {SetValue(KeyProperty, value);}
    }
}
Run Code Online (Sandbox Code Playgroud)

这在页面中消耗如下:

<views:KeyValueView Key="Order Number" Value="{Binding document_number}" />
Run Code Online (Sandbox Code Playgroud)

问题是Key字符串按预期显示,但值字符串不是.我试过在document_number属性上强制一个PropertyChanged事件,这没有帮助.我还尝试在自定义视图的键/值属性的设置器中显式设置标签上的Text属性:

public string Key
    {
        get {return (string)GetValue(KeyProperty);}
        set {
            SetValue(KeyProperty, value);
            KeyLabel.Text = value;
        }
    }
Run Code Online (Sandbox Code Playgroud)

再次这没有帮助,setter代码似乎永远不会被执行(我在它上面放置了一个断点并且它没有被击中)

如果我添加一个开箱即用的控件,例如直接绑定到页面中属性的Label,则会正确显示:

<Label Text="{Binding document_number}"/>
<views:KeyValueView Key="Order Number" Value="{Binding document_number}" />
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么会发生这种情况(或者更确切地说没有发生)?

Dan*_*rda 25

不要在自定义控件内部分配绑定.用这个:

public partial class KeyValueView : ContentView
{
    public KeyValueView()
    {
        InitializeComponent();
        this.VerticalOptions = LayoutOptions.Start;
    }

    public static readonly BindableProperty ValueProperty =
        BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string));

    public string Value
    {
        get {return (string)GetValue(ValueProperty);}
        set {SetValue(ValueProperty, value);}
    }

    public static readonly BindableProperty KeyProperty =
        BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string));

    public string Key
    {
        get {return (string)GetValue(KeyProperty);}
        set {SetValue(KeyProperty, value);}
    }
    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);

        if (propertyName == ValueProperty.PropertyName)
        {
            ValueLabel.Text = Value;
        }
        if (propertyName == KeyProperty.PropertyName)
        {
            KeyLabel.Text = Key;
        }
    }
}

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="KeyValueView">
    <Grid VerticalOptions="Start">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Label x:Name="KeyLabel" Grid.Column="0" HorizontalOptions="Start" />
        <Label x:Name="ValueLabel" Grid.Column="1" HorizontalOptions="EndAndExpand" />
    </Grid>
</ContentView>
Run Code Online (Sandbox Code Playgroud)

将属性(例如,值)视为对BindableProperty(ValueProperty)的引用.如果你在Value setter BindableProperty中做了一些事情,那么BindableProperty将不会收到通知,如果你对BindableProperty做了一些事情(分配/更改ValueProperty),则不会调用属性值setter.

如果要处理PropertyChanged,则可以覆盖(OnPropertyChanged)或Actions(作为创建BindableProperty时的附加参数).