Necromesa
Necromesa

Reputation: 43

Binding DependencyProperty in custom control to ViewModel property

I'm using MVVMCross in my crossplatform native Xamarin app. I seem to have a problem binding boolean properties in my custom control to boolean properties in my ViewModel. For example:

My custom control BarCodeTextBox.cs:

public sealed class BarCodeTextBox : TextBox
{

    public BarCodeTextBox()
    {
        this.DefaultStyleKey = typeof(BarCodeTextBox);
    }

    public bool IsListeningForCodes
    {
        get { return (bool)GetValue(IsListeningForCodesProperty); }
        set {
            SetValue(IsListeningForCodesProperty, value);
            if (value)
            {
                IsReadOnly = true;
                PrefixElement.Visibility = Visibility.Collapsed;
                Window.Current.CoreWindow.CharacterReceived += CoreWindow_CharacterReceived;
            }
            else
            {
                IsReadOnly = false;
                Focus(FocusState.Keyboard);
                PrefixElement.Visibility = Visibility.Visible;
                Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
            }

            Text = string.Empty;
        }
    }


    // Using a DependencyProperty as the backing store for IsListening.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsListeningForCodesProperty =
        DependencyProperty.Register("IsListeningForCodes", typeof(bool), typeof(BarCodeTextBox), new PropertyMetadata(false));

The viewmodel of the page BoxCloseViewModel.cs:

public class BoxCloseViewModel : ViewModelBase
{        
    private bool m_isManualBoxCodeInput;
    public bool IsManualBoxCodeInput
    {
        get { return m_isManualBoxCodeInput; }
        set { SetProperty(ref m_isManualBoxCodeInput, value); }
    }
}

The binding in BoxCloseView.xaml:

<Controls:BarCodeTextBox x:Name="BarCodeInput" Text="{Binding BoxCode, Mode=TwoWay}" IsListeningForCodes="{Binding IsManualBoxCodeInput, Mode=OneWay, Converter={StaticResource BoolToInverseBool}}"/>

When I change the value of IsManualBoxCodeInput in the ViewModel nothing happens in the control (IsListeningForCodes does not change). Things I checked:

Upvotes: 1

Views: 901

Answers (1)

Cameron MacFarland
Cameron MacFarland

Reputation: 71936

Bindings don't call the setter property of a DependencyObject. If you want some code to execute when a binding changes you need to add it as a callback of the PropertyMetadata.

public bool IsListeningForCodes
{
    get { return (bool)GetValue(IsListeningForCodesProperty); }
    set { SetValue(IsListeningForCodesProperty, value); }
}

public static readonly DependencyProperty IsListeningForCodesProperty =
    DependencyProperty.Register("IsListeningForCodes", typeof(bool), typeof(BarCodeTextBox), 
    new PropertyMetadata(false, OnIsListeningForCodesChanged));

static void OnIsListeningForCodesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var instance = (BarCodeTextBox)d;
    instance.OnIsListeningForCodesChanged();
}

void OnIsListeningForCodesChanged()
{
    if (IsListeningForCodes)
    {
        IsReadOnly = true;
        PrefixElement.Visibility = Visibility.Collapsed;
        Window.Current.CoreWindow.CharacterReceived += CoreWindow_CharacterReceived;
    }
    else
    {
        IsReadOnly = false;
        Focus(FocusState.Keyboard);
        PrefixElement.Visibility = Visibility.Visible;
        Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
    }

    Text = string.Empty;
}

Upvotes: 2

Related Questions