locked
Is UserControl dependency property binding broken in Beta 2? RRS feed

  • Question

  • Can anyone confirm or deny this? I cannot seem to find a definitive answer anywhere.

    In any case, in Beta 1 this worked… I have a UserControl with a few custom dependency properties defined.

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace SilverlightApplication3
    {
        public partial class SilverlightControl1 : UserControl
        {
            public SilverlightControl1()
            {
                InitializeComponent();
            }
    
            public static readonly DependencyProperty ButtonTextProperty = DependencyProperty.Register("ButtonText", typeof(string), typeof(SilverlightControl1), null);
            public static readonly DependencyProperty ButtonForegroundProperty = DependencyProperty.Register("ButtonForeground", typeof(Brush), typeof(SilverlightControl1), null);
    
            public string ButtonText
            {
                get
                {
                    return (string)this.GetValue(ButtonTextProperty);
                }
                set
                {
                    base.SetValue(ButtonTextProperty, value);
                }
            }
    
            public Brush ButtonForeground
            {
                get
                {
                    return (Brush)this.GetValue(ButtonForegroundProperty);
                }
                set
                {
                    base.SetValue(ButtonForegroundProperty, value);
                }
            }
        }
    }
    

    In the UserControl’s xaml you used to be able to bind to those properties.

    <UserControl
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="SilverlightApplication3.SilverlightControl1"
        Width="400" Height="300">
        
        <Grid x:Name="LayoutRoot" Background="White">
            <Button Foreground="{Binding ButtonForeground}" Content="{Binding ButtonText}" />
        </Grid>
        
    </UserControl>
    

    And setting their values in whatever xaml used your control.

    <UserControl
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SilverlightApplication3"
        x:Class="SilverlightApplication3.Page"
        Width="400" Height="300">
            
        <Grid x:Name="LayoutRoot" Background="White">
            <local:SilverlightControl1 ButtonForeground="Blue" ButtonText="Hello World!" />
        </Grid>
        
    </UserControl>
    

    See also my initial, related post: Style ControlTemplate Binding not working in beta 2

    Friday, June 20, 2008 11:37 AM

Answers

  • As far as getting this to work now, I would recommend setting the values of your controls in your property changed handlers.  I don't typically try to use bindings on UserControl-derived classes.  You might consider creating a custom control (derived from Control or one of its sub classes).  Then you can use TemplateBinding.

    Friday, June 20, 2008 1:18 PM

All replies

  • Hey,

    There are a few problems with your code and binding to DependencyProperty:

    1. You don't set Binding.Source or DataContext anywhere, so bindings cannot work.
    2. Currently there is a bug that prevents setting DataContext to 'this' (and that's what you probably want to do in UserControl's constructor). This bug will be fixed in the final release.
    3. In Silverlight 2, the binding engine doesn't listen for DependencyProperty changes (it even doesn't recognize that it is a DependencyProperty). Unless you implement INotifyPropertyChanged on your UserControl, the binding target won't be updated when you change the property.

    I hope it helps.

    Regards,
    Tomek

    Friday, June 20, 2008 1:05 PM
  • As far as getting this to work now, I would recommend setting the values of your controls in your property changed handlers.  I don't typically try to use bindings on UserControl-derived classes.  You might consider creating a custom control (derived from Control or one of its sub classes).  Then you can use TemplateBinding.

    Friday, June 20, 2008 1:18 PM
  • Hey,

    There are a few problems with your code and binding to DependencyProperty:

    1. You don't set Binding.Source or DataContext anywhere, so bindings cannot work.
    2. Currently there is a bug that prevents setting DataContext to 'this' (and that's what you probably want to do in UserControl's constructor). This bug will be fixed in the final release.
    3. In Silverlight 2, the binding engine doesn't listen for DependencyProperty changes (it even doesn't recognize that it is a DependencyProperty). Unless you implement INotifyPropertyChanged on your UserControl, the binding target won't be updated when you change the property.

    I hope it helps.

    Regards,
    Tomek

    You're right. In my haste to get this post up I didn't extract all of the relative code for my sample. Looking back at the changesets in TFS I see that I did have a call to base.DataContext = this; in the constructor.  Which I removed due to the StackOverflow error after upgraded to beta 2.  For some reason, I also removed the calls to RaisePropertyChanged and replaced with DependencyProperties after upgrading.

    using System.ComponentModel;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace SilverlightApplication3
    {
        public partial class SilverlightControl1 : UserControl
        {
            private string buttonText;
            private Brush buttonForeground;
    
            public event PropertyChangedEventHandler PropertyChanged;
        	
            public SilverlightControl1()
            {
                InitializeComponent();
                
                base.DataContext = this; // StackOverflowException in Beta 2
            }
    
            private void RaisePropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            public string ButtonText
            {
                get
                {
                    return buttonText;
                }
                set
                {
                    if (buttonText != value)
                    {
                        buttonText = value;
                        RaisePropertyChanged("ButtonText");
                    }
                }
            }
    
            public Brush ButtonForeground
            {
                get
                {
                    return buttonForeground;
                }
                set
                {
                    if (buttonForeground != value)
                    {
                        buttonForeground = value;
                        RaisePropertyChanged("ButtonForeground");
                    }
                }
            }
        }
    }
    

    In any case, the DataContext StackOverflow error is the real issue...  In my case, I have Styles with ControlTemplates which use Binding which are not working now.  I guess I can copy the style templates to the controls to see if I can get it working...

    Friday, June 20, 2008 2:36 PM
  • As far as getting this to work now, I would recommend setting the values of your controls in your property changed handlers.  I don't typically try to use bindings on UserControl-derived classes.  You might consider creating a custom control (derived from Control or one of its sub classes).  Then you can use TemplateBinding.

    Yep, I was able to keep the template binding and get it to work based on your suggestion in my other post. Thanks!

    Friday, June 20, 2008 4:00 PM