Sparers
Sparers

Reputation: 433

Passing an object to a Behaviour in XAML is not working

I have a list of Settings that are a mix of types (int and string, url, ip address etc.) and the parameters that allow these to be validated are stored alongside the actual value in an object. This object is selected from a list of settings and passed to a detail page where the value can be modified.

On the detail page, I have an Entry control that contains the value that requires validation. The Entry takes it's inital value from the ViewModel property SettingItem. This works fine.

I have a Behaviour that i'm going to use to validate the user input to the value on-the-fly however, when the HandleTextChanged method is fired, ItemToValidate is null. I can't work out why.

The 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"
         x:Class="DwyApp.Views.ItemDetailPage"
         xmlns:local="clr-namespace:DwyApp.Behaviours"
         Title="{Binding Title}">
<StackLayout Spacing="20" Padding="15">
    <Label Text="{Binding SettingItem.ParameterName}" FontSize="Medium" FontAttributes="Bold"/>
    <Entry Text="{Binding SettingItem.Value}" FontSize="Medium">
        <Entry.Behaviors>
            <local:ValidateBehaviour ItemToValidate="{Binding SettingItem}" />
        </Entry.Behaviors>
    </Entry>
    <Label x:Name="Value_Error" Text="{Binding SettingItem.ValidationMessage}" FontSize="Medium" IsVisible="{Binding SettingItem.ValidateValue}" TextColor="Red" />
    <Button Text="Save"
            VerticalOptions="Center"
            HorizontalOptions="Center"/>
    <Label Text="{Binding SettingItem.Description}" FontSize="Medium"/>
</StackLayout>

Behaviour:

using DwyApp.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Xamarin.Forms;

namespace DwyApp.Behaviours
{
public class ValidateBehaviour:Behavior<Entry>

{

    public static readonly BindableProperty ItemToValidateProperty = BindableProperty.Create(nameof(ItemToValidate), 
                                                                                            typeof(SettingItem), 
                                                                                            typeof(ValidateBehaviour), 
                                                                                            defaultValue: null);

    public SettingItem ItemToValidate
    {
        get {
            return (SettingItem)GetValue(ItemToValidateProperty);
        }
        set {
            SetValue(ItemToValidateProperty, value);
        }
    }


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

    void HandleTextChanged(object sender, TextChangedEventArgs e)
    {
        bool IsValid = false;
    }

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

}

}

A breakpoint at HandleTextChanged is always hit but the value of ItemToValidate is always null. Any ideas?

Upvotes: 1

Views: 270

Answers (1)

pinedax
pinedax

Reputation: 9356

Change your binding to something like this:

<Entry x:Name="EntryValue" Text="{Binding SettingItem.Value}" FontSize="Medium">
    <Entry.Behaviors>
        <local:ValidateBehaviour                            
                ItemToValidate="{Binding BindingContext.SettingItem, Source={x:Reference EntryValue}}" />
    </Entry.Behaviors>
</Entry>

As you can see I added a x:Name on the Entry and used that value to tell the Binding on the Behaviour what will its Source.

Hope this helps.-

Upvotes: 4

Related Questions