Code from Prism 2.2 and RadDock of that same age worked as far as the prototype we had went, but now I want to take it to Prism 4, and the latest tool set. I want to go MEF as well, but would be happy to see a Unity example that works.
I have this as part of my shell:
<telerikDocking:RadDocking Grid.Column="2" Grid.Row="1" Grid.RowSpan="2">
<telerikDocking:RadDocking.DocumentHost>
<telerikDocking:RadSplitContainer >
<telerikDocking:RadPaneGroup Name="MainRegion" Regions:RegionManager.RegionName="MainRegion">
</telerikDocking:RadPaneGroup>
</telerikDocking:RadSplitContainer>
</telerikDocking:RadDocking.DocumentHost>
</telerikDocking:RadDocking>
I have a RadSplitContainerRegionAdapter and a RadPaneGroupRegionAdapter.
I'm not sure I need both, but they were both there.
My View is a RadPaneGroup which contains a RadPane
Logic tells me this layout gives me a RadPaneGroup inside a RadPaneGroup, but that's what worked in Prism 2.2 with the old tooling.
I've tried making the view be the RadPane to avoid the duplication but it doesn't change anything.
I'm not getting any errors when it runs, just a gray rectangle where the region is.
FWIW... if I remove all the Telerik, the view gets placed into the region just fine.
I'm trying to come up with a minimal-order example of this... sounds like a good blog post if I get permission (assuming we get it running).
Thanks!
-Dave Campbell
35 Answers, 1 is accepted
As it turns out the RadSplitContainerRegionAdapter that was working in Prism 2.2 had a problem with the 'Reset' case in Prism 4. This was getting called and nuking our content.
Removed that section, and changed my project to be Silverlight 4 (a *slight* problem I foisted on myself), and things are wonderful again.
For anyone curious, my shell now has a section like this:
<telerikDocking:RadDocking Grid.Column="2" Grid.Row="1" Grid.RowSpan="2">
<telerikDocking:RadDocking.DocumentHost>
<telerikDocking:RadSplitContainer Name="MainRegion" Regions:RegionManager.RegionName="MainRegion">
</telerikDocking:RadSplitContainer>
</telerikDocking:RadDocking.DocumentHost>
</telerikDocking:RadDocking>
My module is of type RadPaneGroup and the primary container is a RadPane.
Now to convert to MEF :)
Thanks for looking,
-Dave
Thank you for contacting us.
Miroslav Nedyalkov has a blog post about usage of Prism and RadDocking. It is a very basic example, but it could shed some light on the problem. You could find the blog post here - http://blogs.telerik.com/miroslavnedyalkov/posts/09-08-31/using_the_raddocking_control_with_prism.aspx
Also, I would suggest you to refer to our forum thread where you can find interesting notes regarding the usage of Prism and RadDocking.
Meanwhile we are working on a new, more advance example of RadDocking with Prism 4. If you are interested, we could inform you when the example and the blog post are ready.
George
the Telerik team
Here are some updates:
I modified the attached example in the Miroslav Nedyalkov's blog post. Now, it runs without any problems using the Prism 4 dlls. Attached you can find the updated project.
I hope this helps. Looking forward to your reply.
George
the Telerik team
How can we use a view that inherits from UserControl class instead of a RadPane/RadDocumentPane.
Thanks,
Adrien.
I would suggest you to implement a custom region adapter in order to use views that inherit from UserControl. Miroslav's blogpost shows how to use RadDocking with Prism, but you could always change the project in order to suit your needs.
George
the Telerik team
When a second item is added to the RadPaneGroup an exception is thrown.
Value does not fall within the expected range.
Can you explain me what is it pls?
Why the e.Action in the RadPanelGroupRegionAdapter go in "Reset" after adding an element. It causes the collection to be cleared ...
If I comment the code in the "reset" switch, I got the exception shown above.
But I still not understand why the collection event "Reset" is executed after the "add" event.
The current logic is implemented by Microsoft and we don't change anything.
You could refer to the following link - http://msdn.microsoft.com/en-us/library/system.collections.specialized.notifycollectionchangedaction(VS.95).aspx
George
the Telerik team
The specified Visual and this Visual do not share a common ancestor, so there is no valid transformation between the two visuals??
Could you please give us more detailed information how you drop a ScheduleView /or a GridView/ to a pane? Do you use DragAndDrop?
George
the Telerik team
I didnt have the .content tags in the radpane.
I have a question: How can I use RadPaneGroupRegionAdapter when my prism-application using a MefBootstrapper?
In xaml:
<t:RadDocking Grid.Row="1">
<t:RadDocking.DocumentHost>
<t:RadSplitContainer>
<t:RadPaneGroup prism:RegionManager.RegionName="MainShellRegion" />
</t:RadSplitContainer>
</t:RadDocking.DocumentHost>
</t:RadDocking>
but region MainShellRegion is not present in collection of regions. I'm using MEF container.
We will provide an example about how to use RadDocking control with PRISM 4 + MEF in the near future.
George
the Telerik team
Currently i'm looking to that example that you attacht. Now i'm trying to add a new view to the region in the documenthost. I added a button in the shell of your example and in the event handler i wrote :
private void Button_Click(object sender, RoutedEventArgs e)
{
var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
}
now when i look to the regionManager the region defined in the documenthost is dissapeard? Can you give me a clue to solve it?
We are aware of this problem with RadDocumentHost. The issue here is tightly related with the Prism framework and usage the RadPaneGroup in the DocumentHost as Region. If you remove the DocumentHost, everything works as expected. I would suggest you to use the SetRegionManager method to register the pane group as region.
George
the Telerik team
This has been an interesting thread and I have two comments.
1. I also had some issues with the RadDocumentHost. I can see what the problems is. It occurs because as PRISM moves up the visual tree to find the attached RegionManager it fails on the DocumentHost element because the .Parent parameter is returning null. I did not bother trying to go any further into the code to try to solve this... Instead (and I think that this is a good stop gap solution) all that is needed is to have a reference to the RegionManager at the appropriate place.
Personally, I happen to have a Shell structure like this.
<
telerikDocking:RadDocking
x:Name
=
"RadDockinging"
>
<
telerikDocking:RadDocking.DocumentHost
>
<
telerikDocking:RadSplitContainer
x:Name
=
"RadSplitContainerChart"
>
<
telerikDocking:RadPaneGroup
x:Name
=
"RadPaneGroupChart"
Regions:RegionManager.RegionName
=
"DocumentHostRegion"
>
And I have this little bit of magical code in my constructor that looks like this...
public
MainPage(IRegionManager regionManager)
{
InitializeComponent();
RadPaneGroupChart.SetValue( RegionManager.RegionManagerProperty, regionManager);
}
Which, I hope you can see, sets the RegionManager into the attached property of the RadPaneGroup. This works because as PRISM travels up the tree it finds a reference to the RegionManager, thus allowing everything to work.
NOTE: If you are doing any magic work with Scoping of regions things become a lot more messy. But for the average user, this should get them up and running and you are on your own for figuring out which RegionManager you want to reference.
2. I have been using the RadPaneGroupRegionAdapter that y'all have been nice enough to supply to the general public. It works just fine for me and I am going to continue to use it for a while longer. I have found out why the Reset is occurring (it has to do with making sure that the sort occurs when elements are added or removed), but that is not my comment at the moment.
I do not think that the methodology being used is valid. The proper way to accomplish this work should be to have a very simple Adapt method that attaches a new RegionBehaviour to the region. Then all of the work should be accomplished in that class. Much like the TabControlRegionSyncBehaviour and the SelectorItemsSourceSyncBehaviour. I plan to spend some time looking at this in the next few weeks. If I get a solution I'll pass it along, and if that is how your developers are looking at things I'd like to know what they are doing.
Mark,
We appreciate your opinion and we will be glad if you can share with us your code. If you can post a CodeLibrary project it would be great, too.
I am glad to assist you further.
George
the Telerik team
I did a lot of work to let the docking control work with prism. I made a little example project and you can download it here: https://skydrive.live.com/redir.aspx?cid=d1ba3c73be854a97&resid=D1BA3C73BE854A97!472 (the file you need : Prism.TelerikDocking)
What does it contain:
- behavior to get the region manager in the documenthost
- custom regionadapter to have full control over the docking elements
- IPageTitle to set the pagetitle in the viewmodel
- IFocusAware to know with RadPane is the one with focus.
- ICloseAware to have more control over the closing behavior in the docking
what is it not:
- example how to use prism. i don't really use mef and things to init the viewmodels and other feautures of prism are not used. it is just a little example how to use the custom region adapter.
Known issues:
- i think with floating windows there are a few open things. Need to dive more in this scenario.
Anyway to have it using MEF ...
Best regards
Regards
I found your regionadapter very useful in my case, I decided to continue using it but I found some problems
I have structured my dock control as follows:
<
telerik:RadDocking
HasDocumentHost
=
"False"
x:Name
=
"designdock"
Grid.Row
=
"1"
Background
=
"Black"
BorderBrush
=
"Black"
>
<
telerik:RadSplitContainer
InitialPosition
=
"DockedTop"
>
<
telerik:RadPaneGroup
prism:RegionManager.RegionName
=
"DailyUnPostedRegion"
>
<
i:Interaction.Behaviors
>
<
regionbehaviors:ApplyRegionManagerBehavior
/>
</
i:Interaction.Behaviors
>
</
telerik:RadPaneGroup
>
<
telerik:RadPaneGroup
prism:RegionManager.RegionName
=
"DailyUnPostedDetailsRegion"
>
<
i:Interaction.Behaviors
>
<
regionbehaviors:ApplyRegionManagerBehavior
/>
</
i:Interaction.Behaviors
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
<
telerik:RadSplitContainer
InitialPosition
=
"DockedBottom"
>
<
telerik:RadPaneGroup
prism:RegionManager.RegionName
=
"DailyPostedRegion"
>
<
i:Interaction.Behaviors
>
<
regionbehaviors:ApplyRegionManagerBehavior
/>
</
i:Interaction.Behaviors
>
</
telerik:RadPaneGroup
>
<
telerik:RadPaneGroup
prism:RegionManager.RegionName
=
"DailyPostedDetailsRegion"
>
<
i:Interaction.Behaviors
>
<
regionbehaviors:ApplyRegionManagerBehavior
/>
</
i:Interaction.Behaviors
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
</
telerik:RadDocking
>
in the second SplitContainer (at Bottom) when I open any pane and try to close it I got an error in :
d.Close += (p, pp) =>
{
foreach (PrismRadPane pane in pp.Panes)
{
if (pane.OrginalRegion.Views.Contains(pane.Content))
{
pane.OrginalRegion.Remove(pane.Content);
}
}
};
at the bold line saying : The region does not contain the specified view.
What could cause such behavior ...
Appreciate if you could give any resolution to this ....
Excellent, Will be great to have ...
I just need to add another thing; How should I communicate with the created RadPanes, I need for example to be able to trap the close/closepreview to check for any changes in order to submit data to the server.
Another thing is that the PRISM navigation is not working as before, is this normal when using the RegionAdapter?
Appreciate your feedback.
Thanks for the update I will give it a try ...
For the error I reported here it was because my view implement the IRegionLifeTime, that keeps it always true.
also, I have found a way to (not optimal) to communicate with the radpane and check its viewmodel as follows:
private
void
coindock_PreviewClose(
object
sender, Telerik.Windows.Controls.Docking.StateChangeEventArgs e)
{
var dock = ((RadDocking) e.OriginalSource);
var pane = dock.ActivePane
as
PrismRadPane;
var openviews = pane.OrginalRegion.Views;
foreach
(var view
in
openviews)
{
if
(view.GetType() ==
typeof
(CurrencyDetailsView))
{
CurrencyDetailsView v = view
as
CurrencyDetailsView;
if
( ((CurrencyDetailsViewModel)v.DataContext).StateChanged)
{
e.Handled =
true
;
}
}
}
}
I will later need to convert it to MVVM.
Great Work !!
Only for the part were you remove the view from the regionManager
var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
foreach
(var region
in
regionManager.Regions)
{
if
(region.Views.Contains(
this
))
region.Remove(
this
);
}
If I move this code to the ViewModel, nothing happens because the ViewModel isn't aware of the View itself (MVVM concept).
I guess I need to search on this at PRISM, How can I trigger the PRISM to remove the related view.
when you can control it all in the viewmodel you can simple implement ICloseAware at yout viewmodel like IFocusAware and IActiveAware
What i did to get a MVVM pattern is making an abstraction over the region manager thats doing the registration of viewmodels and views. I called it: IViewModelRegionManager
this has a add method like IViewModelRegionManager.AddViewModel(string regionName, object viewModel);
this addviewmodel is gonna look with a viewlocator for an fitting view
the viewmodelregion manager has also a RemoveViewModel(object viewModel) that makes it search in its registrations to the view and then deletes it. In the viewmodel you can use vmRegionManager.RemoveViewModel(this);
i can put that one online too if your interessed but it also depends if you use ViewFirst or ViewModel first approach. I personally love the vm first and use views only as template
Thanks for sharing this ...
I use prism regionManager.RequestNavigation to load the view and I implement the IConfirmNavigationRequest in the VM and it was working fine before I move to RadDock; there I implement the confirmation to close with/out saving to the user and prism takes care of unloading the view VM .
I have found a work around in the VM, if you are interested;
foreach (var region in RegionManager.Regions)
{
foreach (var view in region.Views)
{
if (view is MyDetailsView)
{
if (((MyDetailsView)view).DataContext == this)
{
region.Remove(view);
}
}
}
//if (region.Views.Contains(this)) region.Remove(this);
}
I admit its not generic but it does the work & my view is clean from any CodeBehind.
I am sure your viemodelmanager will be valuable to me, if you can share it as well, will be fabulous.
EDITED:
----------
small detail I forgot to mention (but important) when using prism navigation, I had to have a default view opened before I actually navigate to any other real view (items data), I put a dummy xaml page with "select item to display its content" text message, this is how I trigger the navigation in prism (just in case)
Best regards
I will have a look at the viewmodelregion manager and give you the feedback.
I was using PRISM navigation through all my modules and everything was working as expected, until I decided to use RadDock and I found there are some tweaks to get it to work.
Although I am still use the requestNavigation with no problem and its doing its job just fine,anyway your viewmodel looks promising and I will try to implement it in a big scenario to see how it really works.
One thing; in the close prompt at the Leftview model you still use the old code which doesn't work (doesn't close), I guess you need to call RemoveViewModel or something to get it to work. so I believe the correct code will be:
public
void
DoSomethingASync()
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if
(MessageBox.Show(
"are you sure"
,
"are you sure"
, MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
var regionManager = ServiceLocator.Current.GetInstance<IViewModelRegionManager>();
if
(regionManager.ContainsViewModel(
this
))
{
regionManager.RemoveViewModel(
this
);
}
}
});
}
I will drill deep in the code to understand it better.
Thanks for your information & effort
Regards
Firstly - great work!
Did you manage to get floating windows working? In this version they simply won't appear.
Thanks