1

I've already seen some questions like this one, but the docking library I'd like to use must have an important feature, which was not asked: it must support MVVM.

So, among Telerik, DotNetBar, DevZest, and the other libraries around there (excluding AvalonDock, which I have already tested), is there one you actually use with MVVM?

Thanks in advance

Community
  • 1
  • 1
Emidee
  • 1,245
  • 1
  • 14
  • 33
  • AvalonDock should work, I know people use it with Caliburn Micro. http://goo.gl/gRVo5 – Derek Beattie Sep 20 '11 at 13:18
  • @Derek Beattie: Nope, AvalonDock is not MVVM-compatible. I ran into a lot of trouble for that and had to extend the component. I'll write a blog post about it asap so as to leave it available for any developer in need – Damascus Sep 20 '11 at 13:31
  • Yeah, I'd be curious as to what makes it not Mvvm compatible, I've never used it. – Derek Beattie Sep 20 '11 at 13:34
  • @Mike, i too am facing similar problem. Did you find any library to support MVVM model – Chandermani Jan 23 '12 at 06:30
  • @Chandermani Nope. The project has been on hold for a few monthes. I'm going to have some time to spend on it soon. I'll update the post if I can find a suitable solution – Emidee Jan 23 '12 at 12:48
  • I wrote an article on using AvalonDock with MVVM: http://www.codeproject.com/Articles/239342/AvalonDock-and-MVVM Hope it helps. – Ashley Davis May 04 '12 at 03:02

1 Answers1

2

Hello Mike try with this:

  1. Easy way: Implement Sofa, An adaptation of AvalonDock for Prism
  2. Using AvalonDock and implementing a custom region adapter like this:

    public class ResizingPanelRegionAdapter : RegionAdapterBase<DockingManager>
    {
    public ResizingPanelRegionAdapter(IRegionBehaviorFactory factory)
        : base(factory)
    {
    
    }
    protected override IRegion CreateRegion()
    {
        return new AllActiveRegion();
    }
    
    protected override void Adapt(IRegion region, DockingManager regionTarget)
    {
        region.Views.CollectionChanged += delegate(Object sender, NotifyCollectionChangedEventArgs e)
        {
            OnViewsCollectionChanged(sender, e, region, regionTarget);
        };
    }
    
    private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, DockingManager regionTarget)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            foreach (object item in e.NewItems)
            {
                UIElement view = item as UIElement;
                if (view != null)
                {
                    //Get 
                    ResizingPanel resizingPanel = GetResizingPanel(regionTarget.Content);
                    resizingPanel.Background = Brushes.White;
                    DocumentPane document = GetDocumentPane(resizingPanel.Children);
                    //document.Background = Brushes.White;
    
                    DocumentContent newContentPane = new DocumentContent();
                    newContentPane.Content = item;
                    var itemView = (item as IViewBase);
                    if (itemView != null)
                        newContentPane.Title = itemView.Title;
                    //When contentPane is closed remove the associated region
                    newContentPane.Closed += (contentPaneSender, args) =>
                    {
                        region.Remove(item);
                        newContentPane.Content = null;
                    };
    
                    document.Items.Add(newContentPane);
    
                    if (!resizingPanel.Children.Contains(document))
                        resizingPanel.Children.Add(document);
    
                    regionTarget.Content = resizingPanel;
    
                    newContentPane.Activate();
                    region.Activate(item);
                }
            }
        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
    
        }
    }
    
    private DocumentPane GetDocumentPane(UIElementCollection collection)
    {
        foreach (object item in collection)
        {
            var documentPanel = item as DocumentPane;
            if (documentPanel != null)
                return documentPanel;
        }
        return new DocumentPane();
    }
    
    private ResizingPanel GetResizingPanel(object content)
    {
        var resizingPanel = content as ResizingPanel;
        if (resizingPanel != null)
            return resizingPanel;
        return new ResizingPanel();
    }    
    }
    

And your in your XAML you could implement it like this:

<avalon:DockingManager prism:RegionManager.RegionName="MainRegion">
</avalon:DockingManager>

How it works? Simple, first at all you have to keep in mind that Region adapters are responsible for creating a region and associating it with the control. This allows you to use the IRegion interface to manage the UI control contents in a consistent way.

And a DockingManager is the core control in AvalonDock. It arranges contained panes, handles fly out panes and floating windows.

So, following this example you could have implemented a custom region adapter for avalon, I worked with this implementation in a project getting awesome results.

Regards

mascab
  • 175
  • 2
  • 6
  • Thanks for your answer. Unfortunately, I use CaliburnMicro instead of Prism. I'll have a look at Sofa, to check if I can manage to find a solution – Emidee Oct 13 '11 at 21:47