views:

2249

answers:

1

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.

A: 

The user control's datacontext does not have a Data property.

Because it doesn't have a data property the databinding returns null which is already the default value so the property change never fires.

zachary
I don't get this. Why does it need to have a data property. Not all DCs have a Data property. All my VM classes do not have a Data property. I don't even bind anything to the DC on the child class.
Noam
where you have Binding Datait is telling it to look for a Data property. It doesn't see one and you end up with a null value and it does nothing.
zachary