Brendan
Brendan

Reputation: 19353

Binding not working on custom UserControl in Windows Phone 7

I have a XAML UserControl which defines a fairly basic button - I want to define a Bindable property HasMeasurements which will display an overlay image when HasMeasurements is false . However when I include it in my project and bind it to the ViewModel it does not update consistently.

I am sure the ViewModel is properly notifying the bindings since I have simultenously bound the same ViewModel property to another separate element and it updates as expected. Also it works in Blend when I update the mock data.

I have tried this solution which defines a callback where I change the Visibility programatically, however this callback is not called every time the ViewModel property changes, only sometimes. I have also tried binding the Visibility in the XAML using this solution and a non dependency property which also did not work. I have also tried implementing NotifyPropertyChanged out of desperation but no luck there either ...

Here is my XAML,

<UserControl x:Class="MyApp.View.Controls.ConversionBtn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">

        <Grid x:Name="btnGrid" toolkit:TiltEffect.IsTiltEnabled="True" Height="115">
            <Border Background="{StaticResource ImgOverlayColor}" BorderThickness="0" Padding="0" VerticalAlignment="Top"  >
                <TextBlock x:Name="titleTxtBlock" FontSize="{StaticResource PhoneFontSizeMedium}" Foreground="{StaticResource TileTxtColor}" Margin="6,0,0,0"/>
            </Border>
            <Image x:Name="notAvailableImg" Source="/Images/ConversionNotAvailableOverlay.png" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None" />
        </Grid>

    </Grid>
</UserControl>

Here is the code behind,

// usings here ...

namespace MyApp.View.Controls
{
    public partial class ConversionBtn : UserControl
    {
        public ConversionBtn()
        {
            InitializeComponent();

            if (!TiltEffect.TiltableItems.Contains(typeof(ConversionBtn)))
                TiltEffect.TiltableItems.Add(typeof(ConversionBtn));

            //this.DataContext = this;
        }    

        public string Title
        {
            get { return this.titleTxtBlock.Text; }
            set { this.titleTxtBlock.Text = value; }
        }

        public static readonly DependencyProperty HasMeasurementsProperty =
            DependencyProperty.Register("HasMeasurements", typeof(bool), typeof(ConversionBtn),
            new PropertyMetadata(false, new PropertyChangedCallback(HasMeasurementsPropertyChanged)));

        private static void HasMeasurementsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ConversionBtn cBtn = (ConversionBtn)d;
            bool val = (bool)e.NewValue;
            if (val)
            {
                cBtn.notAvailableImg.Visibility = Visibility.Collapsed;
            }
            else
            {
                cBtn.notAvailableImg.Visibility = Visibility.Visible;
            }
            cBtn.HasMeasurements = val;

        }

        public bool HasMeasurements
        {
            get { return (bool)GetValue(HasMeasurementsProperty); }
            set { SetValue(HasMeasurementsProperty, value); }
        }
    }
}

Upvotes: 0

Views: 842

Answers (2)

Brendan
Brendan

Reputation: 19353

Ah damnit, it was a combination of Anton's answer and the fact that I hadn't set my image as 'Content', hence it loaded in Blend but was not present in the deployed app.

Upvotes: 0

Anton Sizikov
Anton Sizikov

Reputation: 9230

You have a callback, that is called after HasMeasurment propetry was changed.

And in a callback you change it again. So, you have a logical misstake.

If you need to do something with this value - just save it in private field.

    private static void HasMeasurementsPropertyChanged(DependencyObject d, 
DependencyPropertyChangedEventArgs e)
                {
                    ConversionBtncBtn = (ConversionBtn)d;
                    bool val = (bool)e.NewValue;
                    if (val)
                    {
                        cBtn.notAvailableImg.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        cBtn.notAvailableImg.Visibility = Visibility.Visible;
                    }
                    cBtn.SetMeasurments(val); 

                }

            private bool measurmentsState;
            public void SetMeasurments(bool value)
            {
                measurmentsState = value;
            }

Here you can get free e-Book by Charls Petzold about Windows Phone Development, there is a nice chapter about Dependency Properties.

Upvotes: 1

Related Questions