views:

196

answers:

2

Hi We have a user control with a custom dependency property (DP). The DP is bound to an ObservableCollection.

When a new item is added to the collection programatically, the databinding does not update the target DP. Why? We think it's because, unfortunately, in our case the target is not a ListBox or ListView, but a Canvas. The DP, when changed or initialized, is supposed to draw a Shape (!) onto the Canvas, and the shape's position and size is bound to the collection item's two properties: WIDTH, LEFT.

Ideally we don't want to clear the Canvas and redraw all items just becasue one has been added (or deleted). But how?

So: How can the custom DP take care of drawing the shape for the new collection item? What callback do we need, at what point in time does this have to happen, and what specific MetaDataOptions might there?

Also, are there any good resources out there concerning all these dependency property options. They are quite confusing. MSDN does not really help with what we're trying to do.

Thanks!

EDIT:

The ObservableCollection is like so:

public class Projects : ObservableCollection<Project>
{
    //no ommitted code. this class really IS empty!
}

The DP is like so:

public class MyUserControl : UserContorl
{
  public static readonly DependencyProperty... etc. typeof(Projects)

  private static void OnProjectsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MyUserControl u = d as MyUserControl;
        CpProjectCollection projects = e.NewValue as CpProjectCollection;
        u.Refresh(projects);
    }

private void Refresh(CpProjectCollection projects)
        {
           foreach (CpProject p in projects)
            {
              //...add each project to the Canvas
              ProjectContorl pc = new ProjectControl();
              pc.Project = project;

              Binding b = new Binding("StartTime");
              b.Converter = new TimeSpanConverter();
              b.Source = pc.Project;
              b.Mode = BindingMode.TwoWay;
              c.SetBinding(Canvas.LeftProperty, b); 

              //do the same for project duration
            }
        }
    }
+1  A: 
  1. If you bind to ObservableCollection, you get the change notification if the collection is replaced with another collection, not when the collection's content is changed. So, you'll need to subscribe to CollectionChanged event in your code-behind.
  2. If you subscribe to CollectionChanged, you can see which are the new/deleted items in your ObservableCollection. You can add a new shape for each new item and remove old shapes for deleted items.
Vlad
Ok! That is the first step... but if the DP is bound to the collection, when and where would I add the affected item to the canvas? Does that happen in a callback, or do I need certain MetaDataOptions, or a combination of both? I'm clueless as to how this is meant to work. Also, if the canvas holds 10 shapes, and a collection item is deleted, how do I know which one of the 10 shapes represents the deleted item?
John
On second thought, no, the ObservableCollection implements INotifyCollectionChanged already, and with that it fires the CollectionChanged event when an item is added or removed! This is supposed to be the default behavior. What are we doing wrong here?
John
@John: are you subscribing to the `CollectionChanged` event? Maybe you can post your code and tell what exactly is wrong? If you just bind something to an `ObservableCollection`, the binding won't listen on `CollectionChanged`. :-(
Vlad
@Vlad: I posted my code above. As you can see I do not subscribe any event. Where and how would I do that in the MyUserControl? Thanks!
John
A: 

Hey,

Can you please post your code? I'm trying to do something similar (draw on a canvas one shape for each item in my list of items) but I haven't even gotten as far as you!!!

Please help!

DanP
I edited my original post. I hope the code makes some sense. If not, ask me.
John