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

Serialize RadDocking

5 Answers 209 Views
Docking
This is a migrated thread and some comments may be shown as answers.
DANIIl
Top achievements
Rank 1
DANIIl asked on 26 Jun 2015, 08:32 AM

Hi! 

I use RadDocking control to show different content into Tabs (RadPanes). It is necessary to save User settings: RadPanes Headers, order. I realized example from TelerikDemo, but there are two problems:

 

1. I do not want to save/load Content (PaneProxy from example), i want save only objectType of content;

2. Then i load serialized settings size of tabs very small and can't see Headers. 

 

How can i solve these spoblems. 

5 Answers, 1 is accepted

Sort by
0
DANIIl
Top achievements
Rank 1
answered on 29 Jun 2015, 09:01 AM

I forget to write one importante moment!

I use PaneGroupExtension to binding my RadPaneGroup to collection<RadPaneViewModel>. This error is generated by this moment.

 XAML :

<telerik:RadDocking x:Name="SystemObjectsDocking" 
                            AllowDragReorder="True">
            <telerik:RadDocking.DocumentHost>
                <telerik:RadSplitContainer >
                    <telerik:RadPaneGroup x:Name="PaneGroup" 
                                          TabStripPlacement="Top"
                                          local:PaneGroupExtensions.ItemsSource="{Binding}"
                                          local:PaneGroupExtensions.ItemTitleDisplayMemberPath="Header">
                        <local:PaneGroupExtensions.ItemContentTemplate>
                            <DataTemplate>
                                <ContentControl Content="{Binding PaneContent}" />
                            </DataTemplate>
                        </local:PaneGroupExtensions.ItemContentTemplate>
                        <local:PaneGroupExtensions.ItemHeaderTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Header}" />
                            </DataTemplate>
                        </local:PaneGroupExtensions.ItemHeaderTemplate>

                    </telerik:RadPaneGroup>
                </telerik:RadSplitContainer>
            </telerik:RadDocking.DocumentHost>
        </telerik:RadDocking>

 

RADPANEVIEWMODEL: 

 

public class RadPaneViewModel
    {
        /// <summary>
        /// Заголовок панели RadPane
        /// </summary>
        public string Header { get; set; }

        /// <summary>
        /// Содержимое панели RadPane
        /// </summary>
        public object PaneContent { get; set; }

        /// <summary>
        /// Необходимый для сохранения/загрузки настроек параметр
        /// </summary>
        public string SerializationTag { get; set; }
    }

 

 

EXTENSION: 

 

 public class PaneGroupExtensions
    {
        private RadPaneGroup Group { get; set; }

        private Dictionary<object, RadPane> Panes { get; set; }

        private PaneGroupExtensions()
        {
            Panes = new Dictionary<object, RadPane>();
        }

        private void RemoveItem(object paneModel)
        {
            if (Panes.ContainsKey(paneModel))
            {
                var pane = Panes[paneModel];

                pane.RemoveFromParent();

                Panes.Remove(paneModel);
            }
        }

        private void AddItem(object paneModel)
        {
            this.InsertItem(this.Panes.Count, paneModel);
        }

        private void InsertItem(int index, object paneModel)
        {
            if (this.Panes.ContainsKey(paneModel))
                return;

            var pane = new RadPane
            {
                // TODO: Set what needed;
                DataContext = paneModel, 
                Header = paneModel,
                Content = paneModel,
                HeaderTemplate = GetItemHeaderTemplate(this.Group),
                TitleTemplate = GetItemTitleTemplate(this.Group),
                ContentTemplate = GetItemContentTemplate(this.Group)
            };

            RadDocking.SetSerializationTag(pane, ((RadPaneViewModel)paneModel).SerializationTag);

            var titleDisplayMemberPath = GetItemTitleDisplayMemberPath(this.Group) as string;
            if (!string.IsNullOrEmpty(titleDisplayMemberPath))
                pane.SetBinding(RadPane.TitleProperty, new Binding(titleDisplayMemberPath) { Source = paneModel });

            this.Panes.Add(paneModel, pane);

            this.Group.Items.Insert(index, pane);
        }

        public static DataTemplate GetItemHeaderTemplate(DependencyObject obj)
        {
            return (DataTemplate)obj.GetValue(ItemHeaderTemplateProperty);
        }

        public static void SetItemHeaderTemplate(DependencyObject obj, DataTemplate value)
        {
            obj.SetValue(ItemHeaderTemplateProperty, value);
        }

        public static readonly DependencyProperty ItemHeaderTemplateProperty =
            DependencyProperty.RegisterAttached("ItemHeaderTemplate", typeof(DataTemplate), typeof(PaneGroupExtensions), new PropertyMetadata(OnItemHeaderTemplateChanged));

        private static void OnItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var group = d as RadPaneGroup;
            var oldValue = e.OldValue as DataTemplate;
            var newValue = e.NewValue as DataTemplate;
            if (group != null)
            {
                var extension = GetPaneGroupExtension(group);

                if (extension == null)
                    return;

                foreach (var pane in extension.Panes.Values)
                {
                    pane.SetValue(RadPane.HeaderTemplateProperty, newValue);
                }
            }
        }

        public static DataTemplate GetItemTitleTemplate(DependencyObject obj)
        {
            return (DataTemplate)obj.GetValue(ItemTitleTemplateProperty);
        }

        public static void SetItemTitleTemplate(DependencyObject obj, DataTemplate value)
        {
            obj.SetValue(ItemTitleTemplateProperty, value);
        }

        public static readonly DependencyProperty ItemTitleTemplateProperty =
            DependencyProperty.RegisterAttached("ItemTitleTemplate", typeof(DataTemplate), typeof(PaneGroupExtensions), new PropertyMetadata(OnItemTitleTemplateChanged));

        private static void OnItemTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var group = d as RadPaneGroup;
            var oldValue = e.OldValue as DataTemplate;
            var newValue = e.NewValue as DataTemplate;
            if (group != null)
            {
                var extension = GetPaneGroupExtension(group);

                if (extension == null)
                    return;

                foreach (var pane in extension.Panes.Values)
                {
                    pane.SetValue(RadPane.TitleTemplateProperty, newValue);
                }
            }
        }

        public static string GetItemTitleDisplayMemberPath(DependencyObject obj)
        {
            return (string)obj.GetValue(ItemTitleDisplayMemberPathProperty);
        }

        public static void SetItemTitleDisplayMemberPath(DependencyObject obj, string value)
        {
            obj.SetValue(ItemTitleDisplayMemberPathProperty, value);
        }

        public static readonly DependencyProperty ItemTitleDisplayMemberPathProperty =
            DependencyProperty.RegisterAttached("ItemTitleDisplayMemberPath", typeof(string), typeof(PaneGroupExtensions), new PropertyMetadata("", OnItemTitleDisplayMemberPathChanged));

        private static void OnItemTitleDisplayMemberPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var group = d as RadPaneGroup;
            var oldValue = e.OldValue as string;
            var newValue = e.NewValue as string;
            if (group != null)
            {
                var extension = GetPaneGroupExtension(group);

                if (extension == null)
                    return;

                if (string.IsNullOrEmpty(newValue))
                {
                    foreach (var pane in extension.Panes.Values)
                        pane.ClearValue(RadPane.TitleProperty);
                }

                foreach (var paneModel in extension.Panes)
                {
                    // TODO: Update the binding of the Title.
                    extension.Panes[paneModel].SetBinding(RadPane.TitleProperty, new Binding(newValue) { Source = paneModel });
                }
            }
        }

        public static DataTemplate GetItemContentTemplate(DependencyObject obj)
        {
            return (DataTemplate)obj.GetValue(ItemContentTemplateProperty);
        }

        public static void SetItemContentTemplate(DependencyObject obj, DataTemplate value)
        {
            obj.SetValue(ItemContentTemplateProperty, value);
        }

        public static readonly DependencyProperty ItemContentTemplateProperty =
            DependencyProperty.RegisterAttached("ItemContentTemplate", typeof(DataTemplate), typeof(PaneGroupExtensions), new PropertyMetadata(OnItemContentTemplateChanged));

        private static void OnItemContentTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var group = d as RadPaneGroup;
            var oldValue = e.OldValue as DataTemplate;
            var newValue = e.NewValue as DataTemplate;
            if (group != null)
            {
                var extension = GetPaneGroupExtension(group);

                if (extension == null)
                    return;

                foreach (var pane in extension.Panes.Values)
                {
                    pane.SetValue(RadPane.ContentTemplateProperty, newValue);
                }
            }
        }

        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 GetItemsSource(DependencyObject obj)
        {
            return (IEnumerable)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), 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;
            var newValue = e.NewValue as IEnumerable;
            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 paneModel in oldValue)
                    {
                        extension.RemoveItem(paneModel);
                    }

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

                if (newValue != null)
                {
                    foreach (var paneModel in newValue)
                    {
                        extension.AddItem(paneModel);
                    }

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

        private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // TODO: Make better implementation of this.
            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                this.ClearItems();
                foreach (var paneModel in GetItemsSource(this.Group))
                {
                    this.AddItem(paneModel);
                }
            }
            else
            {
                if (e.OldItems != null)
                {
                    foreach (var paneModel in e.OldItems)
                    {
                        this.RemoveItem(paneModel);
                    }
                }

                if (e.NewItems != null)
                {
                    int i = e.NewStartingIndex;
                    foreach (var paneModel in e.NewItems)
                    {
                        this.InsertItem(i++, paneModel);
                    }
                }
            }
        }

        private void ClearItems()
        {
            foreach (var pane in this.Panes.Values)
            {
                pane.RemoveFromParent();
            }

            Panes.Clear();
        }
    }

 

0
Accepted
Vladi
Telerik team
answered on 30 Jun 2015, 02:19 PM
Hi,

Thank you for contacting us.

We are not sure we fully understand the issue you are experiencing. As we see from the provided code snippets you are using the RadDocking in a MVVM scenario with the use of the currently obsolete PaneGroupExtensions approach. I would like to let you know that there is a newer, easier and better way of implementing the control in such MVVM scenarios. With our Q3 2013 SP release of Telerik UI for WPF we introduced the PanesSource and DockingPanesFactory built-in features in the control. With the use of those features you can easily achieve a full MVVM friendly data population of the RadDocking control with RadPane instances. More details could be found in our online documentation here. You can also take a loot at our "CustomDockingPanesFactory" example that is available as a runnable project in our GitHub SDK repository. Could you give this approved appraoch for using the RadDocking control in MVVM friendly scenarios a try and lets us know if you face any issues.

You can download the entire XAML SDK GitHub repository as a zip file directly from here. Also you could take advantage of our SDK Samples Browser application which provides an GitHub free interaction with all of the examples available in our repository. For more details about the Samples Browser application please refer this blog post. If you have any other questions do not hesitate to contact us again.


Regards,
Vladi
Telerik
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 Feedback Portal and vote to affect the priority of the items
0
DANIIl
Top achievements
Rank 1
answered on 01 Jul 2015, 04:29 AM
Thank you, the method with DockingPanesFactory work without problems. It is the ideal solution for me!
0
Sreelaskshmi
Top achievements
Rank 1
answered on 21 Mar 2017, 06:11 AM

Hi Vladi ,

I am using CustomDockingPanesFactory to add the panes.I am able to add panes to Docking.

Panes will be added dynamically , based on user operation.So my requirement is if a new pane is added , that should be open.

Like in visual studio,if we select the Solution explorer from view tab , it will be dock to right dock and open to select files.

Can you please let me which attribute/method do i need to invoke while adding the new pane.

0
Nasko
Telerik team
answered on 23 Mar 2017, 08:49 AM
Hello Sreelaskshmi,

We are not exactly sure that we completely understand the desired by you behavior of RadDocking. Could you please send us a code-snippet of your XAML declaration of the Docking control and your custom DockingPanesFactory?

From the provided description it seems you need the new Pane to be activated when it is added to the PaneGroup. If that is the case that should be working out of the box. A video that demonstrates the current observed by you behavior will also be of great help in order to understand your scenario better.

We are looking forward to hearing from you.

Regards,
Nasko
Telerik by Progress
Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Tags
Docking
Asked by
DANIIl
Top achievements
Rank 1
Answers by
DANIIl
Top achievements
Rank 1
Vladi
Telerik team
Sreelaskshmi
Top achievements
Rank 1
Nasko
Telerik team
Share this question
or