I am using CodePlex wpfmdi container for my WPF application.
I need to bind MdiContainer's children to a viewModel property.
<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite" Children="{Binding Path=Container}"/>
If I do this I am getting this error:
Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.Collections.ObjectModel.ObservableCollection`1[WPF.MDI.MdiChild]'
This is what the Children property in MdiContainer looks like:
public ObservableCollection<MdiChild> Children { get; set; }
What am I doing wrong?
The
Childrenproperty is not exposed as a dependency property, which means you cannot bind it. Furthermore, it is initialized once in the constructor of theMdiContainertype and then a handler is added to theCollectionChangedevent of the underlyingObservableCollection<MdiChild>. It is never updated or removed.Therefore, although the
Childrenproperty has a setter, it will break the control if you use it to set a different collection. This also implies that you cannot simply create attached properties to expose a bindableChildrendependency property.Apart from that,
MdiChildis aControl, so it actually contradicts the purpose of your view model. If you expose a collection of user interface controls from your view model this conflicts with the MVVM pattern. View models should not have any knowledge about the view. However, the MDI controls do not seem to follow the usual WPF practices for custom controls, so there is not much room for improvement here, data templating is not supported, theMdiContaineris aUserControland there are very limited dependency properties.If you really want to continue working with this control with your current approach, you could:
Create a custom attached behavior to synchronize your view model collection with the
Childrencollection of theMdiContainerand vice-versa, see XAML behaviors in WPF.Use the
Loadedevent to assign theChildrencollection to your view model property.Use an
EventTriggeron theLoadedevent with a custom trigger action that sets theChildrencollection. This is just a different variant of the previous approach that does not require code-behind.The new XAML behaviors for WPF package, which replaces the legacy Blend behaviors from the
System.Windows.Interactivitynamespace already includes such a trigger action. Install the Microsoft.Xaml.Behaviors.Wpf NuGet package and use this:Note that with these approaches, you either synchronize to your own collection or you work directly with the collection of the
MdiContainerthat you passed to your view model. These are only workarounds. If you would want to implement this in a clean and MVVM compliant way, I think you would need to extend or fix the control itself, which is rather costly and not recommendable, since it seems to be dead anyway.