Alex Rivera | Logout

Is it possible to bind a Canvas's Children property in XAML?

Asked 2009-05-20T19:36:57.790
59

I'm a little surprised that it is not possible to set up a binding for Canvas.Children through XAML. I've had to resort to a code-behind approach that looks something like this:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    DesignerViewModel dvm = this.DataContext as DesignerViewModel;
    dvm.Document.Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged);

    foreach (UIElement element in dvm.Document.Items)
        designerCanvas.Children.Add(element);
}

private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    ObservableCollection<UIElement> collection = sender as ObservableCollection<UIElement>;

    foreach (UIElement element in collection)
        if (!designerCanvas.Children.Contains(element))
            designerCanvas.Children.Add(element);

    List<UIElement> removeList = new List<UIElement>();
    foreach (UIElement element in designerCanvas.Children)
        if (!collection.Contains(element))
            removeList.Add(element);

    foreach (UIElement element in removeList)
        designerCanvas.Children.Remove(element);
}

I'd much rather just set up a binding in XAML like this:

<Canvas x:Name="designerCanvas"
        Children="{Binding Document.Items}"
        Width="{Binding Document.Width}"
        Height="{Binding Document.Height}">
</Canvas>

Is there a way to accomplish this without resorting to a code-behind approach? I've done some googling on the subject, but haven't come up with much for this specific problem.

I don't like my current approach because it mucks up my nice Model-View-ViewModel by making the View aware of it's ViewModel.

Edit
Report

1 Answer

26

Others have given extensible replies on how to do what you actually want to do already. I'll just explain why you couldn't bind Children directly.

The problem is very simple - data binding target cannot be a read-only property, and Panel.Children is read-only. There is no special handling for collections there. In contrast, ItemsControl.ItemsSource is a read/write property, even though it is of collection type - a rare occurence for a .NET class, but required so as to support the binding scenario.

answered 2009-07-30T21:57:06.170

Your Answer