Serialize RadDocking

4 posts, 1 answers
  1. DANIIl
    DANIIl avatar
    14 posts
    Member since:
    Apr 2015

    Posted 26 Jun 2015 Link to this post

    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. 

  2. DANIIl
    DANIIl avatar
    14 posts
    Member since:
    Apr 2015

    Posted 29 Jun 2015 in reply to DANIIl Link to this post

    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();
            }
        }

     

  3. UI for WPF is Visual Studio 2017 Ready
  4. Answer
    Vladi
    Admin
    Vladi avatar
    744 posts

    Posted 30 Jun 2015 Link to this post

    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
  5. DANIIl
    DANIIl avatar
    14 posts
    Member since:
    Apr 2015

    Posted 30 Jun 2015 in reply to Vladi Link to this post

    Thank you, the method with DockingPanesFactory work without problems. It is the ideal solution for me!
Back to Top