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
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
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.
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.
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.
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!
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.
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 { 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); |
} |
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!
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.
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.
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
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.
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!
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)
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 >>
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;
}
}
}
}
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
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?
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.