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