Unanswered Dependency property registration

  • Monday, July 07, 2008 8:05 PM
     
     
    DependencyProperty.Register and DependencyProperty.RegisterAttached methods contain ownerType parameter.
    The meaning of this parameter is obvious for attached properties: it means that we can use this attached property only with classes of ownerType type (or derived). But I can't understand what does this property mean for DependencyProperty.Register method.

All Replies

  • Tuesday, July 08, 2008 7:14 AM
     
     
    I guess it's just for efficient lookup, since all dependency properties are registered in some central storage system.
    Don't spend too much time thinking about it, just use the type of the class you're declaring the property in ;-)

    hth,
    Marcel
  • Tuesday, July 08, 2008 6:32 PM
     
     
    I would like to know does ownerType influence on something or not.
  • Wednesday, July 09, 2008 7:50 AM
     
     
    I don't even think it would work if you use the type of another class, because all dp's are registered at class level (static), so it needs that type to know which dp's belong to which classes.
    OwnerType is also used if you want to re-use the same dp in another class: http://msdn.microsoft.com/en-us/library/ms754002.aspx.

    Marcel
    • Marked As Answer by Idsa Wednesday, July 09, 2008 11:16 AM
    • Unmarked As Answer by Idsa Wednesday, July 09, 2008 11:41 AM
    • Unmarked As Answer by Idsa Wednesday, July 09, 2008 11:41 AM
    • Unmarked As Answer by Idsa Wednesday, July 09, 2008 11:41 AM
    •  
  • Wednesday, July 09, 2008 11:42 AM
     
     
    But why there is no exception if I use ownerType which is not derived from DependencyObject? RegisterAttached throws such an exception.
  • Wednesday, July 09, 2008 12:59 PM
     
      Has Code

    Just did a little test and it does fail at runtime ("'Class1' type must derive from DependencyObject."). Are you really sure the ownertype does not derive (indirectly) from DependencyObject?

    I did some more testing though. See this xaml:

    <Window x:Class="TempApplication1.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="Window1" Height="300" Width="300">  
        <Grid> 
            <Button x:Name="button1" Click="button1_Click" Width="100" Height="35">  
                Test1  
            </Button> 
        </Grid> 
    </Window> 
     

    Normal use would be this code:
    private void button1_Click(object sender, RoutedEventArgs e)  
    {  
        Button b1 = sender as Button;  
        this.IsAvailable = true;  
    }  
     
    public static readonly DependencyProperty IsAvailableProperty =  
        DependencyProperty.Register("IsAvailable"typeof(bool), typeof(Window1),  
            new FrameworkPropertyMetadata((bool)false,  
                new PropertyChangedCallback(OnIsAvailableChanged)));  
     
    public bool IsAvailable  
    {  
        get { return (bool)GetValue(IsAvailableProperty); }  
        set { SetValue(IsAvailableProperty, value); }  
    }  
     
    private static void OnIsAvailableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
    {  
        MessageBox.Show("IsAvailable changed for: " + d.ToString());  
    Click the button and the MessageBox will tell you that the property has changed for Window1. So far, so good.

    Setting the OwnerType to UIElement still works, because it's a baseclass for Window.
    But it also has a side effect: you can now set this property on any UIElement, for example the button:
    private void button1_Click(object sender, RoutedEventArgs e)  
    {  
        Button b1 = sender as Button;  
        b1.SetValue(Window1.IsAvailableProperty, true);  
    }  
     
    public static readonly DependencyProperty IsAvailableProperty =  
        DependencyProperty.Register("IsAvailable"typeof(bool), typeof(UIElement),  
            new FrameworkPropertyMetadata((bool)false,  
                new PropertyChangedCallback(OnIsAvailableChanged)));  
     
    Now the MessageBox will tell you that the property has changed on the button, but you still handled the changed event in Window1!

    The same would have worked if you had set it to type Button, but using UIElement has another effect when you combine it with 'FrameworkPropertyMetadataOptions.Inherits':
    public static readonly DependencyProperty IsAvailableProperty =  
        DependencyProperty.Register("IsAvailable"typeof(bool), typeof(UIElement),  
            new FrameworkPropertyMetadata((bool)falseFrameworkPropertyMetadataOptions.Inherits,  
                new PropertyChangedCallback(OnIsAvailableChanged)));  
     
    Now the MessageBox will tell you that this property has changed for the the button and all it's children, because they also derive from UIElement!

    So, all this can be useful in very special situations, but I didn't have a need for it yet. Also, I think you can't use this stuff in xaml, only in code.

    hth,
    Marcel
  • Wednesday, July 09, 2008 3:23 PM
     
      Has Code
    Look at this code:
        public partial class Window1 : Window 
        { 
        public static readonly DependencyProperty IsAvailableProperty = DependencyProperty.Register("IsAvailable"typeof(bool), typeof(MyClass)); 
     
            public Window1() 
            { 
              SetValue(IsAvailableProperty, true); 
                InitializeComponent(); 
            } 
        } 
     
        public class MyClass 
        {} 
    MyClass is not derived from DependencyObject, but there is no exception.
  • Wednesday, July 09, 2008 3:44 PM
     
     
    DutchMarcel, dependency property with ownerType set to UIElement is very similar to attached dependency property, doesn't it?
  • Wednesday, July 09, 2008 5:30 PM
     
     
    Idsa said:

    DutchMarcel, dependency property with ownerType set to UIElement is very similar to attached dependency property, doesn't it?


    Yes, I think it is, but an attached property has the advantage that it can be used in xaml aswell.

    I don't know why you don't get an error using the MyClass class, but I'll put my test project up for you to download as soon as I get back at work tomorrow.
  • Thursday, July 10, 2008 7:06 AM
     
     
    I uploaded my test project here: http://cid-027cdb908d14e584.skydrive.live.com/self.aspx/WPFSamples/OwnerTypeTest.zip

    It's using Class1 as the owner type now, so it should fail at runtime with a XamlParseException which, if you look at the details, boils down to a System.ArgmumentException saying: "'Class1' type must derive from DependencyObject."

    If you don't get that exception, it might be that we're running different versions of .NET or Visual Studio? I'm using .NET 3.5 SP1 and VS2008 SP1Beta1.

    hth,
    Marcel
    • Edited by DutchMarcel Thursday, July 10, 2008 7:07 AM wrong link
    •  
  • Saturday, July 12, 2008 4:33 PM
     
      Has Code
    Very interesting, very interesting.
    If you reduce dependency property registration to
    public static readonly DependencyProperty IsAvailableProperty = 
                DependencyProperty.Register("IsAvailable"typeof(bool), typeof(Class1)); 
    there would be no exception. If you extend the registration using Metadata, the exception will be raised. Strange...