views:

21

answers:

1

Hi

Based on this tutorial:

http://www.dotnetfunda.com/articles/article961-wpf-tutorial--dependency-property-.aspx

I've created my usercontrol like this:

usercontrol xaml:

 <UserControl x:Class="PLVS.Modules.Partner.Views.TestControl"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:tp="http://thirdparty.com/controls"
       x:Name="UC">
  <tp:ContainerControl x:Name="tpControl">
    <tp:ContainerControl.Items>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText"/>
      </tp:SomeItem>
    </ig:TabItemEx>
 </tp:ContainerControl.Items>
  </tp:ContainerControl>
</UserControl> 

usercontrol code-behind:

public partial class TestControl : UserControl
{
 public TestControl()
    {
  InitializeComponent();
  SetValue(TestItemsPropertyKey, new ObservableCollection<ThirdPartyClass>());
 }

    public ObservableCollection<ThirdPartyClass> TestItems
    {
      get 
      { 
        return (ObservableCollection<ThirdPartyClass>)GetValue(TabItemsProperty); 
      }
    }

    public static readonly DependencyPropertyKey TestItemsPropertyKey =
      DependencyProperty.RegisterReadOnly("TestItems", typeof(ObservableCollection<ThirdPartyClass>), typeof(TestControl), new UIPropertyMetadata(new ObservableCollection<ThirdPartyClass>(), TestItemsChangedCallback));

 public static readonly DependencyProperty TestItemsProperty = TestItemsPropertyKey.DependencyProperty;

 private static void TestItemsChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
 {
      TestControl ib = obj as TestControl;
  var newNvalue = e.NewValue; // Why is e.NewValue null???
 }
 }

I want to later use the usercontrol like this:

 <localControl:TestControl x:Name="testControl">
 <localControl:TestControl.TabItems>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText2"/>
      </tp:SomeItem>
  <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText3"/>
      </tp:SomeItem>
 </tp:ContainerControl.Items>
 </localControl:TestControl>

In the above code i've added a callback function in my usercontrol so that i can add the new items to the container control "tpControl" declared in the xaml. However when the callback function is triggered the new value is empty. And the question here is why?

A: 

Are you actually seeing e.NewValue as null or as an empty collection?

In your code you're setting a default value for the property to an ObservableCollection instance (which you generally shouldn't do for reference types - just use null) and then assigning another instance of the ObservableCollection in your control's instance constructor, which is triggering the Changed callback. At this point you are now assigning this new empty collection, which is what you should be seeing for e.NewValue.

If you want to access the items declared in XAML you need to wait until after they have been added to the collection. Adding the items will not cause the change handler for the property to fire because you're not assigning a new collection to the DP. You can either use a handler for a different event that occurs later (like Loaded)

    Loaded += (sender, e) => { DoSomething(TestItems) };

or attach a CollectionChanged handler to the e.NewValue instance which will be called each time an item is added, removed, moved, etc.

    var newValue = e.NewValue as ObservableCollection<ThirdPartyClass>;
    newValue.CollectionChanged += (sender, args) => { DoSomething(TestItems); };
John Bowen