将控件绑定到行为属性会尝试将该属性设置为Binding而不是控件

时间:2017-11-10 02:54:40

标签: xamarin.forms

我有以下一组数字条目,其行为应该在输入或删除数字时将焦点移到它们之间:

<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
    <Label>Enter Code</Label>
    <StackLayout Orientation="Horizontal">
        <Entry Keyboard="Numeric" x:Name="FirstDigit" Text="{Binding Digit1}">
            <Entry.Behaviors>
                <behaviours:DigitEntryBehaviour NextDigit="{Binding Source={x:Reference Name=SecondDigit}}" />
            </Entry.Behaviors>
        </Entry>
        <Entry Keyboard="Numeric" x:Name="SecondDigit" Text="{Binding Digit2}">
            <Entry.Behaviors>
                <behaviours:DigitEntryBehaviour PrevDigit="{Binding Source={x:Reference Name=FirstDigit}}" NextDigit="{Binding Source={x:Reference Name=ThirdDigit}}" />
            </Entry.Behaviors>
        </Entry>
        <Entry Keyboard="Numeric" x:Name="ThirdDigit" Text="{Binding Digit3}">
            <Entry.Behaviors>
                <behaviours:DigitEntryBehaviour PrevDigit="{Binding Source={x:Reference Name=SecondDigit}}" NextDigit="{Binding Source={x:Reference Name=FourthDigit}}" />
            </Entry.Behaviors>
        </Entry>
        <Entry Keyboard="Numeric" x:Name="FourthDigit" Text="{Binding Digit4}">
            <Entry.Behaviors>
                <behaviours:DigitEntryBehaviour PrevDigit="{Binding Source={x:Reference Name=ThirdDigit}}" />
            </Entry.Behaviors>
        </Entry>
    </StackLayout>
    <Button Text="Open"></Button>
</StackLayout>

以下是DigitEntryBehaviour

public class DigitEntryBehaviour : Behavior<Entry>
{
    public Entry PrevDigit { get; set; }
    public Entry NextDigit { get; set; }

    protected override void OnAttachedTo(Entry bindable)
    {
        base.OnAttachedTo(bindable);
        bindable.TextChanged += OnEntryTextChanged;
    }

    protected override void OnDetachingFrom(Entry bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.TextChanged -= OnEntryTextChanged;
    }

    private void OnEntryTextChanged(object sender, TextChangedEventArgs e)
    {
        var entry = (Entry)sender;

        if (entry.Text.Length > 1)
        {
            entry.TextChanged -= OnEntryTextChanged;
            entry.Text = e.OldTextValue;
            entry.TextChanged += OnEntryTextChanged;
            string newChar = e.NewTextValue.Substring(1);
            if (NextDigit != null)
                NextDigit.Text = newChar;
        }
        else if (entry.Text.Length > 0)
        {
            NextDigit?.Focus();
        }
        else
        {
            PrevDigit?.Focus();
        }
    }
}

当我尝试运行它时,我得到以下异常:

  

Xamarin.Forms.Xaml.XamlParseException:'位置18:53。无法分配   属性“NextDigit”:属性不存在,或者不可分配,   或者值与属性'

之间的不匹配类型

我尝试将DigitEntryBehaviour的NextDigit和PrevDigit属性的类型设置为object以查看它尝试分配给它们的类型,并且似乎它正在尝试将它们设置为Binding而不是{{ 1}}秒。它为什么这样做?如何才能将Entry正确绑定到这些属性?

1 个答案:

答案 0 :(得分:1)

要使Binding起作用,目标属性必须是可绑定属性,而目标对象应该是BindableObject

由于DigitEntryBehaviour不是BindableObject - 您无法声明可绑定属性 - 因此不会创建绑定。

解决此问题的最简单方法是删除Binding标记扩展,并直接使用Reference扩展名提供Entry控件引用。即NextDigit="{x:Reference Name=SecondDigit}"

更新了XAML

<Entry Keyboard="Numeric" x:Name="FirstDigit" Text="{Binding Digit1}">
    <Entry.Behaviors>
        <behaviours:DigitEntryBehaviour NextDigit="{x:Reference Name=SecondDigit}" />
    </Entry.Behaviors>
</Entry>
<Entry Keyboard="Numeric" x:Name="SecondDigit" Text="{Binding Digit2}">
    <Entry.Behaviors>
        <behaviours:DigitEntryBehaviour PrevDigit="{x:Reference Name=FirstDigit}" NextDigit="{x:Reference Name=ThirdDigit}" />
    </Entry.Behaviors>
</Entry>
<Entry Keyboard="Numeric" x:Name="ThirdDigit" Text="{Binding Digit3}">
    <Entry.Behaviors>
        <behaviours:DigitEntryBehaviour PrevDigit="{x:Reference Name=SecondDigit}" NextDigit="{x:Reference Name=FourthDigit}" />
    </Entry.Behaviors>
</Entry>
<Entry Keyboard="Numeric" x:Name="FourthDigit" Text="{Binding Digit4}">
    <Entry.Behaviors>
        <behaviours:DigitEntryBehaviour PrevDigit="{x:Reference Name=ThirdDigit}" />
    </Entry.Behaviors>
</Entry>