3
votes

I have a custom user control called GoalProgressControl. Another user control contains GoalProgressControl and sets its GoalName attribute via databinding in XAML. However, the GoalName property is never set. When I check it in debug mode GoalName remains "null" for the control's lifetime.

How do I set the GoalName property? Is there something I am doing incorrectly?

I am using .NET Framework 4 and Silverlight 4. I am relatively new to XAML and Silverlight so any help would be greatly appreciated.

I have attempted to change GoalProgressControl.GoalName into a POCO property but this causes a Silverlight error, and my reading leads me to believe that databound properties should be of type DependencyProperty. I've also simplified my code to just focus on the GoalName property (the code is below) with no success.

Here is GoalProgressControl.xaml:

<UserControl x:Class="GoalView.GoalProgressControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Height="100">

<Border Margin="5" Padding="5" BorderBrush="#999" BorderThickness="1">
    <TextBlock Text="{Binding GoalName}"/>
</Border>
</UserControl>

GoalProgressControl.xaml.cs:

public partial class GoalProgressControl : UserControl, INotifyPropertyChanged
{

    public GoalProgressControl()
    {
        InitializeComponent();
    }


    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public static DependencyProperty GoalNameProperty = DependencyProperty.Register("GoalName", typeof(string), typeof(GoalProgressControl), null);
    public string GoalName
    {
        get
        {
            return (String)GetValue(GoalProgressControl.GoalNameProperty);
        }
        set
        {
            base.SetValue(GoalProgressControl.GoalNameProperty, value);
            NotifyPropertyChanged("GoalName");
        }
    }
}

I've placed GoalProgressControl on another page:

    <Grid Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="5" Background="#eee" Height="200">
        <Border BorderBrush="#999" BorderThickness="1" Background="White">
            <StackPanel>
                <hgc:SectionTitleBar x:Name="ttlGoals" Title="Personal Goals" ImageSource="../Images/check.png" Uri="/Pages/GoalPage.xaml" MoreVisibility="Visible" />
                <ItemsControl ItemsSource="{Binding Path=GoalItems}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <!--TextBlock Text="{Binding Path=[Name]}"/-->
                            <goal:GoalProgressControl GoalName="{Binding Path=[Name]}"/>

                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </Border>
    </Grid>

Please note the commented out "TextBlock" item above. If I comment in the TextBlock and comment out the GoalProgressControl, the binding works correctly and the TextBlock shows the GoalName correctly. Also, if I replace the "GoalName" property above with a simple text string (ex "hello world"), the control renders correctly and "hello world" is shown on the control when it renders.

2

2 Answers

4
votes

You have to pass

    new PropertyMetadata(OnValueChanged)

as a last parameter to DependencyProperty.Register call and set the property

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((GoalProgressControl)d).GoalName = (String)e.NewValue;
    }
0
votes

I've written an article on Silverlight 4 Custom Property Binding that you might find useful, and it can be found here: http://nick-howard.blogspot.com/2011/03/silverlight-4-custom-property-binding.html