This question is locked. New answers and comments are not allowed.
Has anyone succeeded in creating a docking implementation that used Caliburn Micro? What I am trying to do is have a docking shell where the only thing it knows about is a toolbox pinned on the side and dynamically loads document panes from external XAPs. The dynamically loading and stuff is easy but I am having trouble figuring out what needs to happen to allow Caliburn to handle the dynamic view creation and have them as the content of dynamically created panes.
I have the Telerik conventions for Caliburn Micro and I'm looking at the RadTabControl changes to allow the conventions to work but docking is a lot more complicated so I am not sure where to begin.
Any help would be greatly appreciated.
Steve
I have the Telerik conventions for Caliburn Micro and I'm looking at the RadTabControl changes to allow the conventions to work but docking is a lot more complicated so I am not sure where to begin.
Any help would be greatly appreciated.
Steve
33 Answers, 1 is accepted
0
Steve
Top achievements
Rank 1
answered on 26 Jul 2011, 03:39 PM
I was able to get it working. I don't think what I have done is 100% ideal but it is good enough for now to see results and can hopefully be tweaked in the future to be better. The key is that CM has to be told to explicitly about the RadPane.
RadPane pane = new RadPane();
Caliburn.Micro.View.SetModel(pane, viewModel);
0
Marc
Top achievements
Rank 1
answered on 06 Oct 2011, 02:59 PM
Hi Steve,
thank you for sharing your ideas. Do you think it's possible to attach the source code of what you did to make Caliburn.Micro's navigation infrastructure work with RadDocking. This would be really helpful for me and probably others as well.
Thanks in advance,
Stephan
thank you for sharing your ideas. Do you think it's possible to attach the source code of what you did to make Caliburn.Micro's navigation infrastructure work with RadDocking. This would be really helpful for me and probably others as well.
Thanks in advance,
Stephan
0
Steve
Top achievements
Rank 1
answered on 19 Oct 2011, 02:46 PM
Stephan,
Sorry I didn't get back to you till now. Here is some of the code. There are some bugs and problems with it but it at least proves the concept. I haven't spent any more time on this piece since I was able to get it to at least partially work. Let me know if you have any questions about it and I'll try to respond quicker :).
Here is the view model. You may have to substitute your MEF loading but the idea is here.
Here is the view. Nothing to it.
Steve
Sorry I didn't get back to you till now. Here is some of the code. There are some bugs and problems with it but it at least proves the concept. I haven't spent any more time on this piece since I was able to get it to at least partially work. Let me know if you have any questions about it and I'll try to respond quicker :).
Here is the view model. You may have to substitute your MEF loading but the idea is here.
[Export(typeof(DockingShellHostViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
public class DockingShellHostViewModel : Conductor<
IModule
>.Collection.AllActive
{
#region Members
private ModuleDefinition m_moduleDefinitionToLoad;
#endregion
#region Constructor
[ImportingConstructor]
public DockingShellHostViewModel(
ICompositionCatalogService a_catalogService)
{
CatalogService = a_catalogService;
ModuleRadPaneGroups = new ObservableCollection<
RadPaneGroup
>();
}
#endregion
#region Properties
private ICompositionCatalogService CatalogService { get; set; }
public ObservableCollection<
RadPaneGroup
> ModuleRadPaneGroups { get; set; }
#endregion
#region Methods
public void LoadModule(ModuleDefinition a_moduleDefinition)
{
m_moduleDefinitionToLoad = a_moduleDefinition;
IdeaBlade.EntityModel.Coroutine.Start(LoadModule);
}
private IEnumerable<
INotifyCompleted
> LoadModule()
{
yield return CatalogService.AddXap(m_moduleDefinitionToLoad.XapName);
object returnModule = CatalogService.GetInstance(typeof(IModule), m_moduleDefinitionToLoad.Module.ToString(), CreationPolicy.NonShared);
if (returnModule != null)
{
if (ModuleRadPaneGroups.Count == 0)
{
RadPaneGroup group = new RadPaneGroup();
ModuleRadPaneGroups.Add(group);
}
RadPane pane = new RadPane();
pane.Header = m_moduleDefinitionToLoad.Title;
// This line tells Caliburn Micro to find the associated view and assign it as the content of the RadPane
// instead of the view model. This is the glue that makes it all work.
Caliburn.Micro.View.SetModel(pane, returnModule);
// Add the pane to the collection so that it is displayed in the UI.
ModuleRadPaneGroups[0].AddItem(pane, Telerik.Windows.Controls.Docking.DockPosition.Center);
pane.Focus();
pane.IsSelected = true;
// Activate the item so that it's life cycle is started.
this.ActivateItem(returnModule as IModule);
}
}
#endregion
}
Here is the view. Nothing to it.
<
UserControl
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
x:Class
=
"..."
xmlns:i
=
"clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cal
=
"http://www.caliburnproject.org"
mc:Ignorable
=
"d"
d:DesignHeight
=
"300"
d:DesignWidth
=
"400"
>
<
UserControl.Resources
>
<
ng:ImageWrapper
x:Key
=
"ImageWrapper"
/>
<
ng:InvertBoolConverter
x:Key
=
"InvertBoolConverter"
/>
</
UserControl.Resources
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"White"
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"*"
/>
</
Grid.RowDefinitions
>
<
telerik:RadMenu
>
<
telerik:RadMenuItem
Header
=
"View"
>
</
telerik:RadMenuItem
>
</
telerik:RadMenu
>
<
telerik:RadDocking
Grid.Row
=
"1"
>
<
telerik:RadDocking.DocumentHost
>
<
telerik:RadSplitContainer
ItemsSource
=
"{Binding ModuleRadPaneGroups}"
>
</
telerik:RadSplitContainer
>
</
telerik:RadDocking.DocumentHost
>
</
telerik:RadDocking
>
</
Grid
>
</
UserControl
>
Steve
0
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 03:24 PM
Thank you Steve,
meanwhile I wrote my own implementation. It basically acts as a mediator between a given IConductor and a (optionally given) RadDocking control using the respective events of each one and creating necessary stuff like panes etc. on the fly.
However, thank you for answering.
Cheers,
Stephan
meanwhile I wrote my own implementation. It basically acts as a mediator between a given IConductor and a (optionally given) RadDocking control using the respective events of each one and creating necessary stuff like panes etc. on the fly.
However, thank you for answering.
Cheers,
Stephan
0
Steve
Top achievements
Rank 1
answered on 19 Oct 2011, 03:27 PM
Stephan,
Glad you were able to get something together. Sounds like the approach you took was a lot better. Would you be able to expound on the idea or post code?
Thanks,
Steve
Glad you were able to get something together. Sounds like the approach you took was a lot better. Would you be able to expound on the idea or post code?
Thanks,
Steve
0
Accepted
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 03:30 PM
There you go:
public class DockManager : IDockManager
{
private IConductActiveItem _conductor;
private RadDocking _dock;
private bool _activatedFromViewModel;
private bool _actuallyClosing;
private bool _deactivateFromViewModel;
private bool _deactivatingFromView;
public void Link(IConductor conductor, FrameworkElement dock = null)
{
if (_conductor != null || _dock != null)
{
throw new InvalidOperationException("Dock manager is already linked");
}
_conductor = conductor as IConductActiveItem;
_dock = dock as RadDocking ?? FindDock();
if (_conductor == null || _dock == null)
{
throw new InvalidOperationException("Invalid conductor or docking control");
}
_conductor.ActivationProcessed += OnActivationProcessed;
_dock.ActivePaneChanged += OnActivePaneChanged;
_dock.PreviewClose += OnPreviewClose;
_dock.Close += OnClose;
}
protected virtual void OnActivationProcessed(object s, ActivationProcessedEventArgs e)
{
if (!e.Success)
{
return;
}
object viewModel = e.Item;
RadPane pane = FindPane(viewModel);
if (pane == null)
{
_activatedFromViewModel = true;
pane = CreatePane(viewModel);
AttachPane(viewModel, pane);
var deactivatable = viewModel as IDeactivate;
if (deactivatable != null)
{
deactivatable.Deactivated += OnDeactivated;
}
}
_dock.ActivePane = pane;
}
protected virtual void OnActivePaneChanged(object s, ActivePangeChangedEventArgs e)
{
if (_activatedFromViewModel)
{
_activatedFromViewModel = false;
return;
}
RadPane pane = e.NewPane;
if (pane == null)
{
return;
}
_conductor.ActivateItem(pane.DataContext);
}
protected virtual void OnDeactivated(object s, DeactivationEventArgs e)
{
if (!e.WasClosed)
{
return;
}
((IDeactivate) s).Deactivated -= OnDeactivated;
if (_deactivatingFromView)
{
return;
}
_deactivateFromViewModel = true;
RemovePane(FindPane(s));
_deactivateFromViewModel = false;
}
protected virtual void OnPreviewClose(object s, StateChangeEventArgs e)
{
RadPane pane = e.Panes.FirstOrDefault();
if (pane == null)
{
return;
}
var guard = pane.DataContext as IGuardClose;
if (guard == null)
{
return;
}
if (e.Handled)
{
return;
}
if (_actuallyClosing)
{
_actuallyClosing = false;
return;
}
bool runningAsync = false;
bool shouldEnd = false;
guard.CanClose(canClose =>
{
Execute.OnUIThread(() =>
{
if (runningAsync && canClose)
{
_actuallyClosing = true;
pane.IsHidden = true;
}
else
{
e.Handled = !canClose;
}
shouldEnd = true;
});
});
if (shouldEnd)
{
return;
}
e.Handled = true;
runningAsync = true;
}
protected virtual void OnClose(object s, StateChangeEventArgs e)
{
RadPane pane = e.Panes.FirstOrDefault();
if (pane == null)
{
return;
}
var deactivatable = pane.DataContext as IDeactivate;
if (deactivatable == null)
{
return;
}
if (_deactivateFromViewModel)
{
return;
}
_deactivatingFromView = true;
RemovePane(pane);
deactivatable.Deactivate(true);
_deactivatingFromView = false;
}
protected virtual RadDocking FindDock()
{
return Application.Current.RootVisual.FindChildByType<
RadDocking
>();
}
protected virtual RadPane FindPane(object viewModel)
{
return _dock.Panes.FirstOrDefault(p => p.DataContext == viewModel);
}
protected virtual RadPane CreatePane(object viewModel)
{
RadPane pane = EnsurePane(viewModel, ViewLocator.LocateForModel(viewModel, null, null));
ViewModelBinder.Bind(viewModel, pane, null);
var haveDisplayName = viewModel as IHaveDisplayName;
if (haveDisplayName != null && !ConventionManager.HasBinding(pane, HeaderedContentControl.HeaderProperty))
{
pane.Header = new DisplayDataControl();
}
return pane;
}
protected virtual RadPane EnsurePane(object viewModel, object view)
{
var pane = view as RadPane;
if (pane == null)
{
pane = new RadPane { DataContext = viewModel, Content = view };
pane.SetValue(View.IsGeneratedProperty, true);
}
return pane;
}
protected virtual void AttachPane(object viewModel, RadPane pane)
{
DockState? dockState = GetDockState(viewModel);
RadSplitContainer splitContainer;
if (dockState == null)
{
splitContainer = _dock.DocumentHost as RadSplitContainer;
if (splitContainer == null)
{
splitContainer = new RadSplitContainer();
splitContainer.SetValue(View.IsGeneratedProperty, true);
_dock.DocumentHost = splitContainer;
}
}
else
{
splitContainer = _dock.Items.OfType<
RadSplitContainer
>().FirstOrDefault(
x => x.GetValue(RadDocking.DockStateProperty) as DockState? == dockState);
if (splitContainer == null)
{
splitContainer = new RadSplitContainer { InitialPosition = dockState.Value };
splitContainer.SetValue(View.IsGeneratedProperty, true);
_dock.Items.Add(splitContainer);
}
}
RadPaneGroup paneGroup = splitContainer.Items.OfType<
RadPaneGroup
>().FirstOrDefault();
if (paneGroup == null)
{
paneGroup = new RadPaneGroup { IsContentPreserved = true };
paneGroup.SetValue(View.IsGeneratedProperty, true);
paneGroup.SelectedItemRemoveBehaviour = SelectedItemRemoveBehaviour.SelectNone;
splitContainer.Items.Add(paneGroup);
}
paneGroup.AddItem(pane, DockPosition.Center);
}
protected virtual void RemovePane(RadPane pane)
{
if (pane == null)
{
return;
}
RadPaneGroup paneGroup = pane.PaneGroup;
pane.RemoveFromParent();
if (paneGroup == null || paneGroup.HasItems)
{
return;
}
RadSplitContainer splitContainer = paneGroup.ParentContainer;
paneGroup.RemoveFromParent();
if (splitContainer == null || splitContainer.HasItems)
{
return;
}
if (splitContainer.IsInDocumentHost)
{
_dock.DocumentHost = null;
}
else
{
_dock.Items.Remove(splitContainer);
}
}
protected virtual DockState? GetDockState(object viewModel)
{
if (viewModel is IHavePaneSettings)
{
var paneSettings = (IHavePaneSettings) viewModel;
switch (paneSettings.InitialState)
{
case PaneState.DockedLeft:
return DockState.DockedLeft;
case PaneState.DockedTop:
return DockState.DockedTop;
case PaneState.DockedRight:
return DockState.DockedRight;
case PaneState.DockedBottom:
return DockState.DockedBottom;
}
}
return null;
}
}
0
Steve
Top achievements
Rank 1
answered on 19 Oct 2011, 04:04 PM
Thank you Stephan. That works like a charm. It will be a great example for extending CM and making it work in a real world app.
Much appreciated,
Steve
Much appreciated,
Steve
0
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 05:03 PM
Thank you Steve,
maybe I'll send this to the Caliburn.Micro community someday.
Two things I'd like to mention:
- When closing the selected pane via UI (not via VM) the RadDocking control always selects the first pane (not what I actually want) even though I set the according behaviour to select-none. More about this here: http://www.telerik.com/community/forums/silverlight/docking/support-for-selecteditemremovebehaviour.aspx
- I never tested the code in OnPreviewClosed when ExecuteOnUIThread runs asynchronously. In case you ever do that, let me know what happened.
Cheers,
Stephan
maybe I'll send this to the Caliburn.Micro community someday.
Two things I'd like to mention:
- When closing the selected pane via UI (not via VM) the RadDocking control always selects the first pane (not what I actually want) even though I set the according behaviour to select-none. More about this here: http://www.telerik.com/community/forums/silverlight/docking/support-for-selecteditemremovebehaviour.aspx
- I never tested the code in OnPreviewClosed when ExecuteOnUIThread runs asynchronously. In case you ever do that, let me know what happened.
Cheers,
Stephan
0
Derek
Top achievements
Rank 1
answered on 19 Oct 2011, 07:30 PM
Stephen, can you post the IDockManager & IHavePaneSettings interfaces?
0
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 07:33 PM
Sure. They're rather simple and generic.
public interface IDockManager
{
void Link(IConductor conductor, FrameworkElement dock = null);
}
public interface IHavePaneSettings
{
PaneState InitialState { get; }
}
public enum PaneState
{
DockedCenter,
DockedLeft,
DockedTop,
DockedRight,
DockedBottom
}
0
Derek
Top achievements
Rank 1
answered on 19 Oct 2011, 07:35 PM
Thanks, I guess I only needed IDocmanager. Nice work on this.
0
Steve
Top achievements
Rank 1
answered on 19 Oct 2011, 07:38 PM
You could simply not implement the interface. I didn't.
Stephan, I would definitely submit it to CM people. It would be nice if Telerik would compile a group of functionality devoted to working with CM. I have found tidbits spread around the forums and other places like making the RadWindow work, conventions, etc.
Stephan, I would definitely submit it to CM people. It would be nice if Telerik would compile a group of functionality devoted to working with CM. I have found tidbits spread around the forums and other places like making the RadWindow work, conventions, etc.
0
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 07:41 PM
Yes, I know. I probably found the same stuff. But unfortunately nothing that fit my needs.
And yes, I will submit this to the CM community in some way. Thank you for your interest.
And yes, I will submit this to the CM community in some way. Thank you for your interest.
0
Derek
Top achievements
Rank 1
answered on 19 Oct 2011, 07:46 PM
Send it to Rob. rob.eisenberg at gmail.com
0
Marc
Top achievements
Rank 1
answered on 19 Oct 2011, 07:51 PM
To the boss himself ???
0
Derek
Top achievements
Rank 1
answered on 19 Oct 2011, 08:01 PM
0
Michele
Top achievements
Rank 2
answered on 07 Nov 2011, 11:02 AM
Hello,
I'm new to CM and Docking..... I've tried to paste in a class
but I got an unknown type for ModuleDefinition and IModule ... what am I missing?
I'm new to CM and Docking..... I've tried to paste in a class
[Export(typeof(DockingShellHostViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
public class DockingShellHostViewModel
...
but I got an unknown type for ModuleDefinition and IModule ... what am I missing?
0
Steve
Top achievements
Rank 1
answered on 07 Nov 2011, 02:00 PM
Paolo,
I wouldn't use the code that I posted. It is not ideal. Stephan's implementation is a lot better and uses CM to the max.
Just so you know, those classes are specific to my implementation. You can replace IModule with whatever interface you are using for MEF. I am dynamically downloading XAPs and modules so they implement IModule. ModuleDefinition is simply a class that has information about the IModule. ModuleDefinition is used because the XAP might need to be downloaded.
Not sure if that is clear enough for you.
Steve
I wouldn't use the code that I posted. It is not ideal. Stephan's implementation is a lot better and uses CM to the max.
Just so you know, those classes are specific to my implementation. You can replace IModule with whatever interface you are using for MEF. I am dynamically downloading XAPs and modules so they implement IModule. ModuleDefinition is simply a class that has information about the IModule. ModuleDefinition is used because the XAP might need to be downloaded.
Not sure if that is clear enough for you.
Steve
0
Derek
Top achievements
Rank 1
answered on 07 Nov 2011, 06:00 PM
I implemented this a little differently. I followed an example from the forums combined with the WindowManager impl.
https://gist.github.com/1345512
edit: I should add, I used Stephen's excellent example and a post from the CM forums as well.
https://gist.github.com/1345512
edit: I should add, I used Stephen's excellent example and a post from the CM forums as well.
0
Michele
Top achievements
Rank 2
answered on 07 Nov 2011, 06:05 PM
Hello Derek,
the implementation you've got is a replacement of RadDocking or it's a must to implement in order to use caliburn & raddocking?
Thanks
the implementation you've got is a replacement of RadDocking or it's a must to implement in order to use caliburn & raddocking?
Thanks
0
Derek
Top achievements
Rank 1
answered on 07 Nov 2011, 06:12 PM
it doesn't replace RadDocking. It lets you use RadDocking like WindowManager.
0
Marc
Top achievements
Rank 1
answered on 08 Nov 2011, 07:00 PM
hi guys,
i just wanted to let you know that i really sent my code to rob eisenberg who kindly reviewed it. he suggested to send it to the author of Caliburn.Micro.Telerik which i tried (see here). additionally i posted it to the CM forum (see here). and now, for the sake of completeness here. below is my current version (custom stuff stripped out). just in case any of you use my previous version: please update because there is a bug (on close an item must be removed through the conductor which in turn deactivates it if possible - previously the items itself got deactivated directly and therefore not removed from the conductor's list).
if anybody finds another bug - please let me know...
regards,
stephan
i just wanted to let you know that i really sent my code to rob eisenberg who kindly reviewed it. he suggested to send it to the author of Caliburn.Micro.Telerik which i tried (see here). additionally i posted it to the CM forum (see here). and now, for the sake of completeness here. below is my current version (custom stuff stripped out). just in case any of you use my previous version: please update because there is a bug (on close an item must be removed through the conductor which in turn deactivates it if possible - previously the items itself got deactivated directly and therefore not removed from the conductor's list).
if anybody finds another bug - please let me know...
regards,
stephan
// A dock manager acts as a mediator between a conductor and an optionally
// given docking control which is typically found in the view of the conductor.
// Even though the interface is pretty simple and generic, it might suffice many
// if not all (?) docking libraries.
public
interface
IDockManager
{
void
Link(IConductor conductor, FrameworkElement dock =
null
);
}
// A view model may wish to implement a dedicated interface (probably dependent
// on the functionality of the concrete docking library) like this to express
// certain docking relevant preferences which can be addressed by the docking manager.
public
interface
IHaveDockPreferences
{
DockingState InitialState {
get
; }
}
public
enum
DockingState
{
DockedCenter,
DockedLeft,
DockedTop,
DockedRight,
DockedBottom
}
// A dock manager is usually injected in the according conductor view model.
// Here we omit the concrete dock control and let the dock manager find it in the
// visual tree. This of course requires that the Link-method is called after the
// conductor's view (which hopefully contains the docking control) is loaded.
public
class
WorkspaceViewModel : Conductor<
object
>.Collection.OneActive
{
[Import]
public
IDockManager DockManager {
get
;
set
; }
protected
override
void
OnViewLoaded(
object
view)
{
base
.OnViewLoaded(view);
DockManager.Link(
this
);
ActivateItem(SomePlainViewModel);
ActivateItem(SomeOtherViewModelWhichImplementsIHaveDockPreferences);
...
}
...
}
// My implementation of IDockManager for Telerik's RadDocking (SL). It basically acts as a
// mediator between a given IConductor (IConductActiveItem in this case) and an optionally
// given docking control (RadDocking in this case) using the respective events of each one
// and creating/removing necessary stuff like panes etc. on the fly.
[Export(
typeof
(IDockManager))]
public
class
DockManager : IDockManager
{
private
IConductActiveItem _conductor;
private
RadDocking _dock;
private
bool
_activatedFromViewModel;
private
bool
_actuallyClosing;
private
bool
_deactivatingFromView;
public
void
Link(IConductor conductor, FrameworkElement dock =
null
)
{
if
(_conductor !=
null
|| _dock !=
null
)
{
throw
new
InvalidOperationException(
"Dock manager is already linked"
);
}
_conductor = conductor
as
IConductActiveItem;
_dock = dock
as
RadDocking ?? FindDock();
if
(_conductor ==
null
|| _dock ==
null
)
{
throw
new
InvalidOperationException(
"Invalid conductor or docking control"
);
}
_conductor.ActivationProcessed += OnActivationProcessed;
_dock.ActivePaneChanged += OnActivePaneChanged;
_dock.PreviewClose += OnPreviewClose;
_dock.Close += OnClose;
}
protected
virtual
void
OnActivationProcessed(
object
s, ActivationProcessedEventArgs e)
{
if
(!e.Success)
{
return
;
}
object
viewModel = e.Item;
RadPane pane = FindPane(viewModel);
if
(pane ==
null
)
{
_activatedFromViewModel =
true
;
pane = CreatePane(viewModel);
AttachPane(viewModel, pane);
var deactivatable = viewModel
as
IDeactivate;
if
(deactivatable !=
null
)
{
deactivatable.Deactivated += OnDeactivated;
}
}
_dock.ActivePane = pane;
}
protected
virtual
void
OnActivePaneChanged(
object
s, ActivePangeChangedEventArgs e)
{
if
(_activatedFromViewModel)
{
_activatedFromViewModel =
false
;
return
;
}
RadPane pane = e.NewPane;
if
(pane ==
null
)
{
return
;
}
_conductor.ActivateItem(pane.DataContext);
}
protected
virtual
void
OnDeactivated(
object
s, DeactivationEventArgs e)
{
if
(!e.WasClosed)
{
return
;
}
((IDeactivate) s).Deactivated -= OnDeactivated;
if
(_deactivatingFromView)
{
return
;
}
RemovePane(FindPane(s));
}
protected
virtual
void
OnPreviewClose(
object
s, StateChangeEventArgs e)
{
RadPane pane = e.Panes.FirstOrDefault();
if
(pane ==
null
)
{
return
;
}
var guard = pane.DataContext
as
IGuardClose;
if
(guard ==
null
)
{
return
;
}
if
(e.Handled)
{
return
;
}
if
(_actuallyClosing)
{
_actuallyClosing =
false
;
return
;
}
bool
runningAsync =
false
;
bool
shouldEnd =
false
;
guard.CanClose(canClose =>
{
Execute.OnUIThread(() =>
{
if
(runningAsync && canClose)
{
_actuallyClosing =
true
;
pane.IsHidden =
true
;
}
else
{
e.Handled = !canClose;
}
shouldEnd =
true
;
});
});
if
(shouldEnd)
{
return
;
}
e.Handled =
true
;
runningAsync =
true
;
}
protected
virtual
void
OnClose(
object
s, StateChangeEventArgs e)
{
RadPane pane = e.Panes.FirstOrDefault();
if
(pane ==
null
)
{
return
;
}
_deactivatingFromView =
true
;
_conductor.CloseItem(pane.DataContext);
RemovePane(pane);
_deactivatingFromView =
false
;
}
protected
virtual
RadDocking FindDock()
{
return
Application.Current.RootVisual.FindChildByType<RadDocking>();
}
protected
virtual
RadPane FindPane(
object
viewModel)
{
return
_dock.Panes.FirstOrDefault(pane => pane.DataContext == viewModel);
}
protected
virtual
RadPane CreatePane(
object
viewModel)
{
RadPane pane = EnsurePane(viewModel, ViewLocator.LocateForModel(viewModel,
null
,
null
));
ViewModelBinder.Bind(viewModel, pane,
null
);
var haveDisplayName = viewModel
as
IHaveDisplayName;
if
(haveDisplayName !=
null
&& !ConventionManager.HasBinding(pane, HeaderedContentControl.HeaderProperty))
{
var binding =
new
Binding(
"DisplayName"
) { Mode = BindingMode.TwoWay };
pane.SetBinding(HeaderedContentControl.HeaderProperty, binding);
}
return
pane;
}
protected
virtual
RadPane EnsurePane(
object
viewModel,
object
view)
{
var pane = view
as
RadPane;
if
(pane ==
null
)
{
pane =
new
RadPane { DataContext = viewModel, Content = view };
pane.SetValue(View.IsGeneratedProperty,
true
);
}
return
pane;
}
protected
virtual
void
AttachPane(
object
viewModel, RadPane pane)
{
DockState? dockState = GetDockState(viewModel);
RadSplitContainer splitContainer;
if
(dockState ==
null
)
{
splitContainer = _dock.DocumentHost
as
RadSplitContainer;
if
(splitContainer ==
null
)
{
splitContainer =
new
RadSplitContainer();
splitContainer.SetValue(View.IsGeneratedProperty,
true
);
_dock.DocumentHost = splitContainer;
}
}
else
{
splitContainer = _dock.Items.OfType<RadSplitContainer>().FirstOrDefault(
container => container.GetValue(RadDocking.DockStateProperty)
as
DockState? == dockState);
if
(splitContainer ==
null
)
{
splitContainer =
new
RadSplitContainer { InitialPosition = dockState.Value };
splitContainer.SetValue(View.IsGeneratedProperty,
true
);
_dock.Items.Add(splitContainer);
}
}
RadPaneGroup paneGroup = splitContainer.Items.OfType<RadPaneGroup>().FirstOrDefault();
if
(paneGroup ==
null
)
{
paneGroup =
new
RadPaneGroup { IsContentPreserved =
true
};
paneGroup.SetValue(View.IsGeneratedProperty,
true
);
paneGroup.SelectedItemRemoveBehaviour = SelectedItemRemoveBehaviour.SelectNone;
splitContainer.Items.Add(paneGroup);
}
paneGroup.AddItem(pane, DockPosition.Center);
}
protected
virtual
void
RemovePane(RadPane pane)
{
if
(pane ==
null
)
{
return
;
}
RadPaneGroup paneGroup = pane.PaneGroup;
pane.RemoveFromParent();
if
(paneGroup ==
null
|| paneGroup.HasItems)
{
return
;
}
RadSplitContainer splitContainer = paneGroup.ParentContainer;
paneGroup.RemoveFromParent();
if
(splitContainer ==
null
|| splitContainer.HasItems)
{
return
;
}
if
(splitContainer.IsInDocumentHost)
{
_dock.DocumentHost =
null
;
}
else
{
_dock.Items.Remove(splitContainer);
}
}
protected
virtual
DockState? GetDockState(
object
viewModel)
{
if
(viewModel
is
IHaveDockPreferences)
{
var dockPreferences = (IHaveDockPreferences) viewModel;
switch
(dockPreferences.InitialState)
{
case
DockingState.DockedLeft:
return
DockState.DockedLeft;
case
DockingState.DockedTop:
return
DockState.DockedTop;
case
DockingState.DockedRight:
return
DockState.DockedRight;
case
DockingState.DockedBottom:
return
DockState.DockedBottom;
}
}
return
null
;
}
}
0
Chuck
Top achievements
Rank 1
answered on 16 Nov 2011, 10:22 PM
Stephan,
This worked like a charm for us. Thanks for posting!
This worked like a charm for us. Thanks for posting!
0
Michele
Top achievements
Rank 2
answered on 28 Nov 2011, 09:46 AM
Hello to everybody,
now that I've created my single models I wish to attach them at load on the workspace but I've no idea about adding them... my workspaceviewmodel (the one that's load from the bootstrapper and that holds a reference to DockManager is defined as )
The single viewmodels are defined as
I've tried using the ActivateItem but in that way I can't set the startup position... how can I do that?
I need to add a menu to the top of the View (that permits the user to select witch operation to do) should I define a model for this? and how can this object tells the dockmanager to position the specific view?
Thanks
Paolo
now that I've created my single models I wish to attach them at load on the workspace but I've no idea about adding them... my workspaceviewmodel (the one that's load from the bootstrapper and that holds a reference to DockManager is defined as )
[Export]
public class WorkspaceViewModel : Conductor<
object
>.Collection.OneActive
{
[Import]
public IDockManager DockManager { get; set; }
private IWindowManager _manager;
private IApplicationRepository _repository;
[ImportingConstructor]
public WorkspaceViewModel(IApplicationRepository repository, IWindowManager manager)
{
base.DisplayName = "myapp";
_manager = manager;
_repository = repository;
}
protected override void OnViewLoaded(object view)
{
base.OnViewLoaded(view);
DockManager.Link(this);
UserMessagesViewModel model = new UserMessagesViewModel(_repository);
ActivateItem(model);
}
}
The single viewmodels are defined as
[Export]
public class UserMessagesViewModel : Screen
{
...
}
I've tried using the ActivateItem but in that way I can't set the startup position... how can I do that?
I need to add a menu to the top of the View (that permits the user to select witch operation to do) should I define a model for this? and how can this object tells the dockmanager to position the specific view?
Thanks
Paolo
0
Michele
Top achievements
Rank 2
answered on 28 Nov 2011, 09:46 AM
duplicate post... sorry... I recevied a Server Error message
0
Michele
Top achievements
Rank 2
answered on 01 Dec 2011, 11:34 AM
anyone can help me ?
Thanks
Thanks
0
Hello Paolo,
Miroslav Nedyalkov
the Telerik team
Could you please explain in more details what you need to achieve and how you interact with the Docking control? Is the ActiveItem the ActivePane property of the Docking control? If you could prepare a sample project that demonstrates the idea this would be of great help for us to understand the problem you are experiencing.
Regards,Miroslav Nedyalkov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Michele
Top achievements
Rank 2
answered on 06 Dec 2011, 10:20 AM
Hello Miroslav,I've gone a little bit further in these days and I'm able to load an item, so this part is ok... I've got still some iussues about how to organize my models in the sense : I've got 30 view/viewmodels...should my WorkSpaceViewModel contain a reference to each view viewmodel? is there some Activator/Factory that can help me?
0
Michele
Top achievements
Rank 2
answered on 06 Dec 2011, 10:21 AM
Each time I reply to this post I got a server error message... can you please verify?
0
asen
Top achievements
Rank 1
answered on 06 Dec 2011, 10:55 AM
Hi Paolo,
Currently there is a bug related to this thread. We are working on it and it will be fixed in the nearest future. Do not hesitate to post new messages. They will be delivered successfully, however unfortunately you will continue to see the error message screenfor some more time.
Currently there is a bug related to this thread. We are working on it and it will be fixed in the nearest future. Do not hesitate to post new messages. They will be delivered successfully, however unfortunately you will continue to see the error message screenfor some more time.
0
Hello Paolo,
Miroslav Nedyalkov
the Telerik team
We cannot advice you on this matter as this depends on your project requirements and architecture. I apologize for not being able to assist.
Regards,Miroslav Nedyalkov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Noemata
Top achievements
Rank 1
answered on 29 Apr 2014, 05:28 PM
Has anyone done anything more recent, the material here is getting dated. In addition, none of the information presented here is complete enough to derive a working example. In particular, the view binding details are not presented for the RadDock control, either for the DockManager implementation or the RadDockingManager implementation mentioned and shown here: https://gist.github.com/dbeattie71/1345512??
It would be very helpful to have more examples showing Telerik integration with Caliburn.Micro given how popular this particular framework is.
It would be very helpful to have more examples showing Telerik integration with Caliburn.Micro given how popular this particular framework is.
0
Hello Mario,
Thank you for your feedback about runnable examples of RadDocking integration with the Caliburn Micro framework.
We will do our best to create such example and include it in our online SDK repository at GitHub. You can find the repository at the following address:https://github.com/telerik/xaml-sdk
Regards,
Vladi
Telerik
Thank you for your feedback about runnable examples of RadDocking integration with the Caliburn Micro framework.
We will do our best to create such example and include it in our online SDK repository at GitHub. You can find the repository at the following address:https://github.com/telerik/xaml-sdk
Regards,
Vladi
Telerik
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.