13

I'm creating an app in which a list of objects should be intercepted and translated before being displayed on a group of controls. To this end, I've created a DependencyProperty of type ObservableCollection (BackupEntry being a custom class defining information about a database). What I want to happen is that the control will be bound to an ObservableCollection in a MVVM. This collection could be used to initially load the control. Then, when an entry is added via the control interface, it should be added to the internal ObservableCollection which is defined as a DependencyProperty and show up in the collection in the MVVM since they are bound. Here's the code that I'm using:

protected ObservableCollection<BackupEntry> _BackupItems = new ObservableCollection<BackupEntry>();

public static readonly DependencyProperty BackupItemsProperty = DependencyProperty.Register("BackupItems", typeof(ObservableCollection<BackupEntry>), typeof(ExplorerWindow));

public ObservableCollection<BackupEntry> BackupItems
{
    get { return (ObservableCollection<BackupEntry>)GetValue(BackupItemsProperty); }
    set { SetValue(BackupItemsProperty, value); }
}

public ExplorerWindow()
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(ExplorerWindow), new FrameworkPropertyMetadata(typeof(ExplorerWindow)));
    SetValue(BackupItemsProperty, _BackupItems);
    _BackupItems.CollectionChanged += new NotifyCollectionChangedEventHandler(BackupItems_CollectionChanged);
}

void BackupItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    throw new NotImplementedException();
}

And in the test app:

<my:ExplorerWindow Name="ew" HorizontalAlignment="Left" VerticalAlignment="Top" Width="503" Height="223" BackupItems="{Binding BackupListItems}" />

I created a button on the screen in my test app. When it is clicked, an item is added to BackupListItems. BackupItems_CollectionChanged is never called and the new item is not shown in my collection in my control. Am I totally off track here? What do I need to do to get this working?

Dirk Dastardly
  • 1,017
  • 2
  • 12
  • 23
  • Is the above code your ViewModel ? If so, why are you using Dependency objects rather than Properties – Dean Chalk Aug 12 '11 at 13:34
  • No, the above code is codebehind for my control. There is no direct correlation between the data being entered into the list and the controls that are being used to display it. The DependencyObject is meant to expose the list so that it can be bound and data passed to and from the control. – Dirk Dastardly Aug 12 '11 at 14:07

2 Answers2

11

You should follow the pattern given in this question. You need to subscribe to the CollectionChanged event within the PropertyChanged handler as is shown in the above link.

Community
  • 1
  • 1
Jakub
  • 534
  • 3
  • 17
0

the collection changed event is only subscribed to for the default value of BackupItems that you set in the ExplorerWindow constructor. You then replace the default value with the collection in your viewmodel - which you haven't subscribed to. You need to subscribe to collectionchanged every time the property is set. You can use the overload of DependencyProperty.Register that accepts a PropertyMetadata and supply a callback for when the property changes. Here's a rough sketch - haven't compiled it but should point you in the right direction.

 public static readonly DependencyProperty BackupItemsProperty = DependencyProperty.Register(
    "BackupItems", 
    typeof(ObservableCollection<BackupEntry>), 
    typeof(ExplorerWindow), 
    OnBackupItemsChanged);

private void OnBackupItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var old = (ObservableCollection<BackupEntry>)e.OldValue;
    if (old != null) 
    {
       old.CollectionChanged -= BackupItems_CollectionChanged;
    }
    ((ObservableCollection<BackupEntry>)e.NewValue).CollectionChanged += BackupItems_CollectionChanged;
}

void BackupItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    throw new NotImplementedException();
}
saus
  • 2,136
  • 17
  • 15