Dependency Properties and Data Context in Silverlight 3

Posted by Noam on Stack Overflow See other posts from Stack Overflow or by Noam
Published on 2009-06-15T08:46:14Z Indexed on 2010/04/17 22:03 UTC
Read the original article Hit count: 536

Hello,

I am working with Silverlight 3 beta, and am having an issue. I have a page that has a user control that I worte on it. The user control has a dependency property on it. If the user control does not define a data context (hence using the parent's data context), all works well. But if the user control has its own data context, the dependency property's OnPropertyChanged method never gets called.

Here is a sample:

My Main Page:

    <UserControl x:Class="TestDepProp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:app="clr-namespace:TestDepProp"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="100">
    <Grid x:Name="LayoutRoot" Background="White">
        <Border BorderBrush="Blue" BorderThickness="3" CornerRadius="3">
            <StackPanel Orientation="Horizontal">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="Enter text here:" />
                    <TextBox x:Name="entryBlock" Text="{Binding Data, Mode=TwoWay}"/>
                    <Button Content="Go!" Click="Button_Click" />
                    <TextBlock Text="{Binding Data}" />
                </StackPanel>
                <Border BorderBrush="Blue" BorderThickness="3" CornerRadius="3" Margin="5">
                    <app:TestControl PropOnControl="{Binding Data}" />
                </Border>
            </StackPanel>
        </Border>
    </Grid>
</UserControl>

Main Page code:

    using System.Windows;
using System.Windows.Controls;

namespace TestDepProp
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            MainPageData data = new MainPageData();

            this.DataContext = data;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            int i = 1;
            i++;
        }
    }
}

Main Page's data context:

    using System.ComponentModel;

namespace TestDepProp
{
    public class MainPageData:INotifyPropertyChanged
    {

        string _data;
        public string Data
        {
            get
            {
                return _data;
            }
            set
            {
                _data = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Data"));
            }
        }

        public MainPageData()
        {
            Data = "Initial Value";
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

Control XAML:

    <UserControl x:Class="TestDepProp.TestControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:app="clr-namespace:TestDepProp"
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical" Margin="10" >
            <TextBlock Text="This should change:" />
            <TextBlock x:Name="ControlValue" Text="Not Set" />
        </StackPanel>
    </Grid>
</UserControl>

Contol code:

    using System.Windows;
using System.Windows.Controls;

namespace TestDepProp
{
    public partial class TestControl : UserControl
    {
        public TestControl()
        {
            InitializeComponent();
            // Comment out next line for DP to work
            DataContext = new MyDataContext();
        }


        #region PropOnControl Dependency Property

        public string PropOnControl
        {
            get { return (string)GetValue(PropOnControlProperty); }
            set { SetValue(PropOnControlProperty, value); }
        }

        public static readonly DependencyProperty PropOnControlProperty =
                    DependencyProperty.Register("PropOnControl", typeof(string), typeof(TestControl), new PropertyMetadata(OnPropOnControlPropertyChanged));

        private static void OnPropOnControlPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TestControl _TestControl = d as TestControl;
            if (_TestControl != null)
            {
                _TestControl.ControlValue.Text = e.NewValue.ToString(); 
            }
        }
        #endregion PropOnControl Dependency Property

    }
}

Control's data context:

    using System.ComponentModel;

namespace TestDepProp
{
    public class MyDataContext : INotifyPropertyChanged
    {

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

To try it out, type something in the text box, and hit the Go button. Comment out the data context in the controls code to see that it starts to work.

Hope someone has an idea as to what is going on.

© Stack Overflow or respective owner

Related posts about silverlight-3.0

Related posts about datacontext