This is a migrated thread and some comments may be shown as answers.

Can not drag RadPane when binding the itemssource to RadPaneGroup

19 Answers 458 Views
Docking
This is a migrated thread and some comments may be shown as answers.
ricky wu
Top achievements
Rank 1
ricky wu asked on 15 Mar 2010, 08:42 PM
Hi,
    I am binding the itemssource property of RadPaneGroup in my viewmodel. The binding property type is observablecollection<RadPane> in my viewmodel.
    After i loaded RadPane in Radpane group through observablecollection<RadPane>, I failed to drag and dock the radpane, which throw exception: operation not supported on read only collection. This exception supposed throw when i edit the itmessouce property in the code behind. I suspect is the docking also modify the state of itemssource?
Ricky

My Xaml:

 

 

 

<telerikcontrol:RadDocking 

 

 

    <telerikcontrol:RadSplitContainer>

 

    <!--<telerikcontrol:RadPaneGroup x:Name="TopWidgets" ItemsSource="{Binding TopWidgets}"     Height="Auto"     FontSize="30">-->

 

 

 

 

        <telerikcontrol:RadPaneGroup>

 

 

 

 

             <telerikcontrol:RadPane  x:Name="TopWidgets">
                <
Button Width="20" Height="30"></Button>
            </
telerikcontrol:RadPane>

 

 

 

 

 

 

 

 

        </telerikcontrol:RadPaneGroup>

 

 

 

 

 

 

    </telerikcontrol:RadSplitContainer>

 

 

 

 

 

 

    <telerikcontrol:RadSplitContainer>

 

 

 

 

        <telerikcontrol:RadPaneGroup   ItemsSource="{Binding BottomWidgets}" x:Name="BottomWidgets"            Height="Auto"  FontSize="30">

 

 

 

         </telerikcontrol:RadPaneGroup>

 

 

 

 

    </telerikcontrol:RadSplitContainer>

 

 

 

 

 

 

My viewmodel:
public MainViewModel(){
    BottomWidgets = new ObservableCollection<RadPane>();
}

 

public

 

 

ObservableCollection<RadPane> BottomWidgets{get;set;}

 

 //Can be called from codebehind trigged by event

 public void InsertRadPanel()

 

 

{
    RadPane rp = new Radpane(){ Header = "AddedPane"}
    BottomWidgets.Add(rp);

 

}

 My code behind:

 public MainPage{
    MainViewModel mvm;
    public MainPage(){
        mvm = new MailViewModel();
        this.DataContext = mvm;    
   }
    private void btn_click(sender s, event e){
            mvm.InsertRadPanel();
    }

 

 

 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

19 Answers, 1 is accepted

Sort by
0
ricky wu
Top achievements
Rank 1
answered on 16 Mar 2010, 03:29 PM

After investigate in details. I found the exception
Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E; Tablet PC 2.0; MALC)
Timestamp: Tue, 16 Mar 2010 14:15:59 UTC

Message: Unhandled Error in Silverlight Application
Code: 4004   
Category: ManagedRuntimeError      
Message: System.InvalidOperationException: Operation not supported on read-only collection.
   at System.Windows.Controls.ItemCollection.RemoveImpl(Object value)
   at System.Windows.Controls.ItemCollection.RemoveInternal(Object value)
   at System.Windows.PresentationFrameworkCollection`1.Remove(T value)
   at Telerik.Windows.Controls.RadPaneGroup.RemovePane(RadPane pane)
   at Telerik.Windows.Controls.RadPane.RemoveFromParent()
   at Telerik.Windows.Controls.RadDocking.MoveItems(RadTabControl source, RadTabControl destination)
   at Telerik.Windows.Controls.RadDocking.OpenInToolWindow(RadPaneGroup radPaneGroup)
   at Telerik.Windows.Controls.RadDocking.ShowElement(DragInfoEventArgs e)
   at Telerik.Windows.Controls.RadDocking.OnDragDelta(Object sender, DragInfoEventArgs e)
   at Telerik.Windows.Controls.Docking.DragInfoEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at Telerik.Windows.RadRoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at Telerik.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RadRoutedEventArgs routedEventArgs)
   at Telerik.Windows.RouteItem.InvokeHandler(RadRoutedEventArgs routedEventArgs)
   at Telerik.Windows.EventRoute.InvokeHandlersImpl(Object source, RadRoutedEventArgs args, Boolean raisedAgain)
   at Telerik.Windows.EventRoute.InvokeHandlers(Object source, RadRoutedEventArgs args)
   at Telerik.Windows.RadRoutedEventHelper.RaiseEvent(DependencyObject element, RadRoutedEventArgs args)
   at Telerik.Windows.DependencyObjectExtensions.RaiseEvent(DependencyObject element, RadRoutedEventArgs e)
   at Telerik.Windows.Controls.Docking.DragDropHelper.DragDelta(UIElement target, UIElement dragRoot, MouseEventArgs e)
   at Telerik.Windows.Controls.Docking.DragDropHelper.DragDelta(UIElement target, MouseEventArgs e)
   at Telerik.Windows.Controls.Docking.PaneHeader.OnMouseMove(MouseEventArgs e)
   at System.Windows.Controls.Control.OnMouseMove(Control ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)    

Line: 54

 

0
Kaloyan
Telerik team
answered on 18 Mar 2010, 12:48 PM
Hi ricky wu,

You observations are leading you to the correct direction. The RadDocking doesn't support binding and
 is using the ItemsSource property of its component parts(RadSplitContainer, RadPaneGroup, etc, etc).

Kind regards,
Kaloyan
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
ricky wu
Top achievements
Rank 1
answered on 18 Mar 2010, 01:21 PM
Actually, the itemssource property is bindable, that is why i can load it from observablecollection. I guess the docking drag did not use the binding property.
Are you plan to support data binding on docking control? It is very important for making a decision of control for my company.
I am sure there are tons of people using mvvm model for sivlerlight application developement. Decouple design is the way to go.
 It would be nice if you add this feature.
0
Accepted
Miroslav Nedyalkov
Telerik team
answered on 19 Mar 2010, 10:21 AM
Hello Ricky,

As Kaloyan alread said using the ItemsSource property of the PaneGroup control is not supported. The property is there and it is bindable because it is inhereted from the ItemsControl class, but it is actually not supporeted. You could refer to the attached example - it demonstrates a way to work-around this limitation.

Kind regards,
Miroslav Nedyalkov
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
ricky wu
Top achievements
Rank 1
answered on 19 Mar 2010, 04:34 PM
Thanks, I got it works by your example, my manager must happy with it.
0
Calabonga
Top achievements
Rank 2
answered on 02 Jun 2010, 12:02 AM
Please answer me will you have plans to make ItemsSource property of the PaneGroup control is bindable (MVVM, MEF). Because that's very important for our project. We plan to buy yours Silverlight Controls.
0
Miroslav Nedyalkov
Telerik team
answered on 03 Jun 2010, 02:10 PM
Hello Calabonga,

 We don't have such plans, because it is very complicated for us to manipulate the original ItemsSource when you are dragging panes around. For PRISM we created a custom RegionAdapter that solves the problem with PRISM. You could refer to the following article that describes how to use it: http://blogs.telerik.com/miroslavnedyalkov/posts/09-08-31/using_the_raddocking_control_with_prism.aspx.

If you just need to bind to a collection you could use the approach implemented in the attached project (there are attached properties for ItemsSource and DataTemplates for Headers, Titles and Content.

Hope this helps!

Greetings,
Miroslav Nedyalkov
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Calabonga
Top achievements
Rank 2
answered on 03 Jun 2010, 10:30 PM

I understand that realization this feature is very complicated. But I need just to bind to collection (just MVVM, not Prizm).
I already using "attached property binding" solution which I found on forum. But I get some error when click to return to page (Navigation Application) where I'm using your RadDocking control (please see the attachment):

"The element is already the child of another element."

And I don't understand why it happening. Please can you help me to solve this problem:

public class PaneGroupExtensions  
    {  
        private RadPaneGroup Group { getset; }  
 
        private static PaneGroupExtensions GetPaneGroupExtension(DependencyObject obj)  
        {  
            return (PaneGroupExtensions)obj.GetValue(PaneGroupExtensionProperty);  
        }  
 
        private static void SetPaneGroupExtension(DependencyObject obj, PaneGroupExtensions value)  
        {  
            obj.SetValue(PaneGroupExtensionProperty, value);  
        }  
 
        private static readonly DependencyProperty PaneGroupExtensionProperty =  
            DependencyProperty.RegisterAttached("PaneGroupExtension"typeof(PaneGroupExtensions), typeof(PaneGroupExtensions), null);  
 
        public static IEnumerable<RadPane> GetItemsSource(DependencyObject obj)  
        {  
            return (IEnumerable<RadPane>)obj.GetValue(ItemsSourceProperty);  
        }  
 
        public static void SetItemsSource(DependencyObject obj, IEnumerable<RadPane> value)  
        {  
            obj.SetValue(ItemsSourceProperty, value);  
        }  
 
        public static readonly DependencyProperty ItemsSourceProperty =  
            DependencyProperty.RegisterAttached("ItemsSource"typeof(IEnumerable<RadPane>), typeof(PaneGroupExtensions), new PropertyMetadata(null, OnItemsSourceChanged));  
 
        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
        {  
            var group = d as RadPaneGroup;  
            var oldValue = e.OldValue as IEnumerable<RadPane>;  
            var newValue = e.NewValue as IEnumerable<RadPane>;  
            var oldValueObservableCollection = e.OldValue as INotifyCollectionChanged;  
            var newValueObservableCollection = e.NewValue as INotifyCollectionChanged;  
 
            if (group != null)  
            {  
                var extension = GetPaneGroupExtension(group);  
                if (extension == null)  
                {  
                    extension = new PaneGroupExtensions { Group = group };  
                    SetPaneGroupExtension(group, extension);  
                }  
 
                if (oldValue != null)  
                {  
                    foreach (var pane in oldValue)  
                    {  
                        pane.RemoveFromParent();  
                    }  
 
                    if (oldValueObservableCollection != null)  
                    {  
                        oldValueObservableCollection.CollectionChanged -= extension.OnItemsSourceCollectionChanged;  
                    }  
                }  
                  
                 
                if (newValue != null)  
                {  
                    foreach (var pane in newValue)  
                    {  
                        pane.RemoveFromParent();  
                    }  
 
 
                    foreach (var pane in newValue)  
                    {  
                        group.Items.Add(pane);  
                    }  
 
                    if (newValueObservableCollection != null)  
                    {  
                        newValueObservableCollection.CollectionChanged += extension.OnItemsSourceCollectionChanged;  
                    }  
                }  
            }  
        }  
 
        private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)  
        {  
            if (e.Action == NotifyCollectionChangedAction.Reset)  
            {  
                this.Group.Items.Clear();  
                foreach (var pane in GetItemsSource(this.Group))  
                {  
                    this.Group.Items.Add(pane);  
                }  
            }  
            else 
            {  
                if (e.OldItems != null)  
                {  
                    foreach (var pane in e.OldItems.OfType<RadPane>())  
                    {  
                        pane.RemoveFromParent();  
                    }  
                }  
 
                if (e.NewItems != null)  
                {  
                    int i = e.NewStartingIndex;  
                    foreach (var pane in e.NewItems.OfType<RadPane>())  
                    {  
                        this.Group.Items.Insert(i, pane);  
                    }  
                }  
            }  
        }  
    } 

To find the solution for this problem is very impotent to me!

0
Miroslav Nedyalkov
Telerik team
answered on 09 Jun 2010, 09:00 AM
Hello Calabonga,

 You could change the code in this line to check if the pane already has parent to call its RemoveFromParent method and after that adds it to the Items of the group.

If this doesn't help, please send us a sample project that reproduces the problem.

All the best,
Miroslav Nedyalkov
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Calabonga
Top achievements
Rank 2
answered on 09 Jun 2010, 11:07 PM
thanks for the advice, I will definitely check this method
0
John
Top achievements
Rank 1
answered on 25 Jul 2011, 06:49 PM

Hi Miroslav,

I've been using the approach that you implemented in dockingandmvvm.zip that you provided, in order to be able to bind the RadDocking control to a datasource using MVVM. So far it has been working great. However I have now encoutered an issue. When placing a radgridview in the content datatemplate, the grid correctly appears when the pane is docked. However as soon as I undock the pane, the data dissappears from the grid. XAML is below: 

 

<

 

 

Grid x:Name="LayoutRoot" Background="White">

 

 

 

 

<telerik:RadDocking x:Name="radDocking1" Background="White" BorderThickness="0" BorderBrush="{x:Null}" Padding="0">

 

 

 

 

    <

 

 

telerik:RadDocking.DocumentHost>

 

 

 

 

        <telerik:RadSplitContainer>

 

 

 

 

            <telerik:RadPaneGroup local:PaneGroupExtensions.ItemsSource="{Binding Panes}">

 

                <

 

 

local:PaneGroupExtensions.ItemContentTemplate>

 

 

 

 

                    <DataTemplate>

 

 

 

 

                            <telerik:RadGridView ItemsSource="{Binding DataContext.MyData, ElementName=LayoutRoot}"></telerik:RadGridView>

 

 

 

 

 

 

 

 

                    </DataTemplate>

 

 

 

 

 

 

 

 

                </local:PaneGroupExtensions.ItemContentTemplate>

 

 

 

 

 

 

 

 

            </telerik:RadPaneGroup>

 

 

 

 

 

 

 

 

        </telerik:RadSplitContainer>

 

 

 

 

 

 

 

 

    </telerik:RadDocking.DocumentHost>

 

 

 

 

 

 

 

 

</telerik:RadDocking>

 

<

 

 

/Grid>

 

Can you please let me know how to resolve this issue?

Thanks
John

0
George
Telerik team
answered on 29 Jul 2011, 12:50 PM
Hi John,

 

The ElementName binding in a DataTemplate works only when the ElementName target and the object are in one and same scope. In the current scenario, the LayoutRoot grid and the panes are in one and same UserControl, but the floating panes are located in a separated ToolWindows, outside of the UserControl. This is the reason why the binding fails when a pane goes floating.

I would suggest binding the Grid to a property from the RadPane DataContext, not from the Grid DataContext. This could resolve your issue because the RadPane doesn't lose its DatContext when goes floating.

Hope this helps.


Best wishes,
George
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
John
Top achievements
Rank 1
answered on 29 Jul 2011, 01:48 PM
Many thanks George. That worked a treat!
0
Nick
Top achievements
Rank 1
answered on 19 Aug 2011, 08:13 AM
Hi There

I have tried the dockingandmvvm example, and have replaced the content from a string to a usercontrol.
the issue is that when I try to drag or select any pane that has already been selected I get the following error:

Value does not fall within the expected range.


at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.SetValue(IManagedPeerBase obj, DependencyProperty property, DependencyObject doh)
at MS.Internal.XcpImports.SetValue(IManagedPeerBase doh, DependencyProperty property, Object obj)
at System.Windows.DependencyObject.SetObjectValueToCore(DependencyProperty dp, Object value)
at System.Windows.DependencyObject.SetEffectiveValue(DependencyProperty property, EffectiveValueEntry& newEntry, Object newValue)
at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp)
at System.Windows.Data.BindingExpression.SendDataToTarget()
at System.Windows.Data.BindingExpression.SourceAcquired()
at System.Windows.Data.BindingExpression.System.Windows.IDataContextChangedListener.OnDataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.Data.BindingExpression.DataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent, Boolean bIsNewParentAlive)
at System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent, IManagedPeer newParent, Boolean bIsNewParentAlive, Boolean keepReferenceToParent)
at MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate(IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Byte bIsParentAlive, Byte bKeepReferenceToParent, Byte bCanCreateParent)
0
Konstantina
Telerik team
answered on 23 Aug 2011, 03:30 PM
Hello Nick,

We will continue the conversation in the support ticket. Thank you.

Kind regards,
Konstantina
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
David
Top achievements
Rank 1
answered on 13 Dec 2011, 10:02 PM
I used your source code soultion and works pretty well except when  I try to add new pane it throw and ""Value does not fall within the expected range. error when we call " Group.Items.Insert(i++, pane)"  


code snipit
case NotifyCollectionChangedAction.Add:                    
 if (e.NewItems != null)                     
{                         
int i = e.NewStartingIndex;                         
foreach (RadPane pane in e.NewItems.OfType<RadPane>())                         
{                             
Group.Items.Insert(i++, pane);   
 }                     
}


here is the whole class

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using Telerik.Windows.Controls;

namespace FOCUS.Plugin.Infrastructure.Silverlight.Extensions
{
    public class PaneGroupExtensions
    {
        private static readonly DependencyProperty PaneGroupExtensionProperty =
            DependencyProperty.RegisterAttached("PaneGroupExtension", typeof (PaneGroupExtensions),
                                                typeof (PaneGroupExtensions), null);

        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.RegisterAttached("ItemsSource", typeof (IEnumerable<RadPane>),
                                                typeof (PaneGroupExtensions),
                                                new PropertyMetadata(null, OnItemsSourceChanged));

        private RadPaneGroup Group { get; set; }

        private static PaneGroupExtensions GetPaneGroupExtension(DependencyObject obj)
        {
            return (PaneGroupExtensions) obj.GetValue(PaneGroupExtensionProperty);
        }

        private static void SetPaneGroupExtension(DependencyObject obj, PaneGroupExtensions value)
        {
            obj.SetValue(PaneGroupExtensionProperty, value);
        }

        public static IEnumerable<RadPane> GetItemsSource(DependencyObject obj)
        {
            return (IEnumerable<RadPane>) obj.GetValue(ItemsSourceProperty);
        }

        public static void SetItemsSource(DependencyObject obj, IEnumerable<RadPane> value)
        {
            obj.SetValue(ItemsSourceProperty, value);
        }

        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var group = d as RadPaneGroup;
            var oldValue = e.OldValue as IEnumerable<RadPane>;
            var newValue = e.NewValue as IEnumerable<RadPane>;
            var oldValueObservableCollection = e.OldValue as INotifyCollectionChanged;
            var newValueObservableCollection = e.NewValue as INotifyCollectionChanged;

            if (group != null)
            {
                PaneGroupExtensions extension = GetPaneGroupExtension(group);
                if (extension == null)
                {
                    extension = new PaneGroupExtensions {Group = group};
                    SetPaneGroupExtension(group, extension);
                }

                if (oldValue != null)
                {
                    foreach (RadPane pane in oldValue)
                    {
                        pane.RemoveFromParent();
                    }

                    if (oldValueObservableCollection != null)
                    {
                        oldValueObservableCollection.CollectionChanged -= extension.OnItemsSourceCollectionChanged;
                    }
                }

                if (newValue != null)
                {
                    foreach (RadPane pane in newValue)
                    {
                        group.Items.Add(pane);
                    }

                    if (newValueObservableCollection != null)
                    {
                        newValueObservableCollection.CollectionChanged += extension.OnItemsSourceCollectionChanged;
                    }
                }
            }
        }

        private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Reset:
                    Group.Items.Clear();
                    foreach (RadPane pane in GetItemsSource(Group))
                    {
                        Group.Items.Add(pane);
                    }
                    break;
                case NotifyCollectionChangedAction.Add:
                    if (e.NewItems != null)
                    {
                        int i = e.NewStartingIndex;
                        foreach (RadPane pane in e.NewItems.OfType<RadPane>())
                        {
                            Group.Items.Insert(i++, pane);
                            //Group.Items.Add(pane);
                        }
                    }

                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldItems != null)
                    {
                        foreach (RadPane pane in e.OldItems.OfType<RadPane>())
                        {
                            pane.RemoveFromParent();
                        }
                    }
                    break;
            }
        }
    }
}

0
Konstantina
Telerik team
answered on 15 Dec 2011, 01:53 PM
Hi David,

Could you please open a support ticket and send us the whole project, so that we can review it and debug it locally. In that way we will be able to provide you with solution in a timely manner.

Looking forward to your reply.

All the best,
Konstantina
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Jegan
Top achievements
Rank 1
answered on 07 Jan 2015, 04:14 PM
Hi Miroslav

I am using the docking and MVVM example to host collection of panes with a content template. It is all working fine except that when an item in the collection is updated, the PaneGroupExtensions doesn't get the update. Is there any work around for this?
0
Nasko
Telerik team
answered on 08 Jan 2015, 02:58 PM
Hi Jegan,

I have noticed that you've ask the same question in this forum thread. I have already replied you and will ask you to continue the conversation there.

Hopes this helps.

Regards,
Nasko
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Tags
Docking
Asked by
ricky wu
Top achievements
Rank 1
Answers by
ricky wu
Top achievements
Rank 1
Kaloyan
Telerik team
Miroslav Nedyalkov
Telerik team
Calabonga
Top achievements
Rank 2
John
Top achievements
Rank 1
George
Telerik team
Nick
Top achievements
Rank 1
Konstantina
Telerik team
David
Top achievements
Rank 1
Jegan
Top achievements
Rank 1
Nasko
Telerik team
Share this question
or