akaphenom
akaphenom

Reputation: 6888

F# Silverlight 3.0 Custom Control Property throws: NullReferenceException

I have defined a Control with:

 static member ItemsProperty : DependencyProperty = 
        DependencyProperty.Register(
            "Items",
            typeof<MyMenuItemCollection>,
            typeof<MyMenu>,
            null);

 member this.Items
        with get () : MyMenuItemCollection = this.GetValue(MyMenu.ItemsProperty) :?> MyMenuItemCollection
        and set (value: MyMenuItemCollection) = this.SetValue(MyMenu.ItemsProperty, value);

The problem occurs on access:

for menuItem in this.Items do
    let contentElement: FrameworkElement = menuItem.Content

where I get a null reference exception on this.Items;

'Items' threw an exception of type 'System.NullReferenceException'

Immediately after I initialized in the constructor:

do
    this.Items <- new CoolMenuItemCollection()

Upvotes: 0

Views: 243

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243061

I think the problem is that static member in F# doesn't correspond to public field as you may have expected, but to a property with get member. This means, that each time you acccess this.ItemsProperty, you're actually creating a new dependency property.

You can create a static field like this:

type Control = 
  // private static field
  static let itemsProperty : DependencyProperty =  
    DependencyProperty.Register
      ("Items", typeof<MyMenuItemCollection>, typeof<MyMenu>, null); 
  // public static property with getter 
  static member ItemsProperty = itemsProperty  

  // You can use both private 'itemsProperty' field or public property here
  member this.Items 
    with get () : MyMenuItemCollection = 
      this.GetValue(itemsProperty) :?> MyMenuItemCollection 
    and set (value: MyMenuItemCollection) = 
      this.SetValue(itemsProperty, value) 

Upvotes: 1

Jeff Wilcox
Jeff Wilcox

Reputation: 6385

The CLR getter is NOT called by most of the framework. That is for the convienience of developer access is code behind files.

Inside your constructor would be a great place to initialize the collection if you need to.

Do NOT set a default value (null in your dependency property declaration above) to an empty collection. The default value is a shared, single static instance - so every instance of your control would share that same list, not what you are intending.

Upvotes: 0

Related Questions