Hi,
I'm trying to create a similar layout to visual studio using RadDocking and prism regions. The xaml is as follows:
<tcd:RadDocking Grid.Row="2" Grid.ColumnSpan="3">
<tcd:RadDocking.DocumentHost>
<tcn:RadTabControl
regions:RegionManager.RegionName="MainRegion"
infRegions:RadTabControlRegionAdapter.ItemContainerStyle="{StaticResource MainRegionTabControlItemStyle}"
AllowDragReorder="True"/>
</tcd:RadDocking.DocumentHost>
<tcd:RadSplitContainer InitialPosition="DockedLeft">
<tcd:RadPaneGroup>
<tcd:RadPane Header="Task">
<tcd:RadPane.Content>
<ContentControl regions:RegionManager.RegionName="LeftRegion" />
</tcd:RadPane.Content>
</tcd:RadPane>
</tcd:RadPaneGroup>
</tcd:RadSplitContainer>
<tcd:RadSplitContainer InitialPosition="DockedRight">
<tcd:RadPaneGroup>
<tcd:RadPane Header="Task">
<tcd:RadPane.Content>
<ContentControl regions:RegionManager.RegionName="RightRegion" />
</tcd:RadPane.Content>
</tcd:RadPane>
</tcd:RadPaneGroup>
</tcd:RadSplitContainer>
<tcd:RadSplitContainer InitialPosition="DockedBottom">
<tcd:RadPaneGroup>
<tcd:RadPane Header="Task">
<tcd:RadPane.Content>
<ContentControl regions:RegionManager.RegionName="BottomRegion" />
</tcd:RadPane.Content>
</tcd:RadPane>
</tcd:RadPaneGroup>
</tcd:RadSplitContainer>
</tcd:RadDocking>
The left, right and bottom regions work as expected i.e. I can add and remove views as required. The problem is with the main region. Unfortunately, prism does not add the MainRegion to the RegionManager and I thus can't load any content. I thought the problem might be something to do the Tabcontrol (even though I have used this in other applications) so I amended the code as follows:
<tcd:RadDocking.DocumentHost>
<ContentControl regions:RegionManager.RegionName="MainRegion"/>
</tcd:RadDocking.DocumentHost>
Again we have the same problem; the region is not added to the RegionManager. I have tried manually adding the region in the code behind by directly referencing the framework element and calling the RegionManager.SetRegionName() method. Again no luck. I think the problem relates to document host however I can't think why. Any ideas?
Thanks in advance
Ian
51 Answers, 1 is accepted
Attached, you can find a small Prism application demonstrating the approach you want to achieve. The project build is including the latest RadControls for Silverlight binaries (version - 2009.1.605). Don't hesitate to contact us in case you need more explanation.
All the best,
Kaloyan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
Thanks for the quick reply. Your app demostrates how to use raddocking with prism view discovery however unfortunetly I need to implement view injection. Your app resolves a view and loads it in to a region once the region is created. It does this by using the following syntax:
regionManager.RegisterViewWithRegion("MainRegion", typeof(MainRegion));
Unfortunetly I need to use the following syntax as I need to add and remove views on demand:
IRegion mainRegion = _regionManager.Regions[RegionNames.MainRegion];
mainRegion.Add(view, "MainRegionView");
In anycase, your app has confirmed something that I couldn't previously explain. I thought the MainRegion never got created however I now think the MainRegion (in RadDocking.DocumentHost) gets created and is then deactivated shortly after. I'm not exactly sure why this is however the region is definietly not in the RegionManager.Regions collection (i.e. is not a SingleActiveRegion?).
In investigating this issue I have, frustratingly, found another problem. The left and right regions in your app will deactivate if unpinned. This is not much of a problem in my app as I will load content only once into the docked left and right regions (i.e. I can use view discovery). I don't really care if the regions are subsequently de-activated. The problem is with the main region as I need to continually add and remove content (views). So the question is what causes the main region to deactivate? And how can I prevent it?
I can prevent the left and right regions from deactivating by setting the IsPinned property to true. I wonder if there is a property I can set that will keep the main region activate?
Thanks in advance
Ian
This time we were able to reproduce the issue but after spearing a lot of time of debugging, our team couldn't find the real bug that causes the problem you described. I am attaching a new modified version of the Prism and RadDock project which contains a simple workaround of this issue.
Hope this helps.
Kaloyan
the Telerik team
Instantly find answers to your questions on the newTelerik Support Portal.
Check out the tipsfor optimizing your support resource searches.
We had a similar issue, so I hope the following helps.
For the RadDock Tab controls (your MainRegion - inside DocumentHost), the View Discovery method of loading a View into the TabRegion works fine, but the View Injection method fails - it says it can't find the TabRegion in the RegionManager.
This fails with an exception - use of View Injection in TabRegion
_regionManager.Regions[RegionNames.TabRegion].Add(new HtmlHostView());
This works - use of View Discovery in TabRegion. Note how the new view is created using a lambda expression, rather than the new() constructor.
_regionManager.RegisterViewWithRegion(RegionNames.TabRegion, () => new HtmlHostView());
This works - while it uses View Injection the the view is NOT being added to the TabRegion.
_regionManager.Regions[RegionNames.DockedLeftRegion].Add(new HtmlHostView());
See http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=53610 (which suggests the solution) and http://blogs.southworks.net/jdominguez/2008/04/using-the-presentation-model-in-wpf/ for details.
Good luck
Julian
PS. We're doing similar work with RadDocking and Prism, but found that if we defined Prism regions on RadPaneGroups we could load new RadPanes into these regions, but then got an exception whenever we Unpinned, Closed, or undocked (to floating) a RadPane. You may be ok because you're not defining regions on RadPaneGroups.
Xaml:
<radDock:RadSplitContainer radDock:DockingPanel.InitialSize="400,400" Name="LeftContainer" InitialPosition="DockedLeft">
<radDock:RadPaneGroup Regions:RegionManager.RegionName="DockedLeftRegion">
<radDock:RadPane Header="Is Inside Prism Region, so will error when unpinned, closed or undocked">
<TextBlock TextWrapping="Wrap">Test</TextBlock>
</radDock:RadPane>
</radDock:RadPaneGroup>
</radDock:RadSplitContainer>
Exception:
{System.InvalidOperationException: Operation not supported on read-only collection.
at System.Windows.Controls.ItemCollection.RemoveInternal(Object value)
at System.Windows.PresentationFrameworkCollection`1.Remove(T value)
at Telerik.Windows.Controls.RadPaneGroup.UnpinPane(RadPane pane)
at Telerik.Windows.Controls.Docking.AutoHideArea.UnpinPane(RadPane pane)
at Telerik.Windows.Controls.RadDocking.UnpinPane(RadPane radPane, AutoHideArea area, Boolean stopEvents)
at Telerik.Windows.Controls.RadDocking.RadPane_PinChange(Object sender, PinChangeEventArgs args)
Is this possible with the docking control?
As a solution I am suggesting that you attach the Region property to a RadTabControl and when you add a new view you can add it to the RadTabControl as a RadTabItem. Please find attached a small project demonstrating this approach. Don't hesitate to write us if this does not prompt to your needs.
Best wishes,
Kaloyan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
thanks for the reply, but that is unfortunately not exactly what I meant. I'll try to clarify more what I mean.
I would like to be able to register a new view with the LeftRegion in the example for instance which would result in this view being rendered as a new RadPane. So I would like to be able to say someting like:
regionManager.RegisterViewWithRegion("LeftRegion", () => new LeftView());
I would like that a new RadPane is added to the LeftRegion which has the LeftView as content.
Is this possible with the RadDocking, or should I try to create a RegionAdapter for this? Has anybody maybe already tried to do this?
Hi Koen
We've tried to do exactly what you're trying - see my previous post on 25 June.
The trick is to define the regions on RadPaneGroups inside a RadSplitContainer. For example:
<radDock:RadSplitContainer radDock:DockingPanel.InitialSize="400,400" Name="LeftContainer" InitialPosition="DockedLeft">
<radDock:RadPaneGroup Regions:RegionManager.RegionName="DockedLeftRegion">
You can then add a new RadPane to the region :
regionManager.RegisterViewWithRegion("DockedLeftRegion", () => new LeftView());
Note that LeftView should inherit from RadPane because the Prism region is defined on a RadPaneGroup which expects RadPane children.
The problem (as detailed in my previous post) is that you get an exception whenever you Unpin, Close, or undock (to floating) the new RadPane (LeftView in the example above), as the default Prism RegionAdapters don't handle removing a registered view from the visual tree.
To fix this and continue to use Prism regions with RadDocking, you'll need to create a new RegionAdapter for RadPaneGroups.
We didn't have time to do this on our project, so we simply removed any use of Prism regions from the main page and created a simple utility class (called DockManager and registered with the Unity container so that Prism modules can access it) that allowed us to add new views (deriving from RadPane) to named RadPaneGroups.
Julian
As Julin said, the prefer approach is to set the RegionName attached property to the RadPaneGroup.The view you want to add to the Region must derive form RadPane or set the new View as a content of the RadPane.Check the code bellow:
regionManager.RegisterViewWithRegion("LeftRegion", |
() => |
{ |
var pane = new RadPane() { Title = "New RadPane" }; |
pane.Content = new LeftRegion(); |
return pane; |
}); |
Kind regards,
Kaloyan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
Any progress on this? I'm beginning a multi-year project that will leverage Prism on the docking control. Getting the shell and supporting services right in the first phase is of upmost importance to the success of later phases. Some of the features planned:
- user will be able to save one or more main screen layouts
- based upon the user's settings, load one of multiple shell layouts. User will need to switch between these layouts at run-time. These different layouts are essentially a saved layout loading into different regions.
- modules may be pinned or unpinned
- a user may only have access to a portion of the available modules
- will be loading localization for the user
- a main area document document area based upon work from other regions, so we will be dynamically creating tabs to show detailed data forms.
From this thread it appears I should be looking at building a custom RegionAdapter for the docking control?
Thanks,
Paul from Minneapolis
The problem here is that when you pin/unpin/close a RadPane, the RadDocking automatically changes the RadPaneGroup where it is stored. Which is probably interfering with the Prism API (perhaps it is not allowed to change the region of the define view). As for now, creating an own RegionAdapter seems to be the only solution for the issue. Keep in mind, that RadDocking is not completely tested with the Prism infrastructure. Sorry once again for the inconvenienced caused.
Best wishes,
Kaloyan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
Thanks for the prompt reply. Having to create a custom RegionAdapter is some extra work, yes, but I'd rather do that then have to build my own docking control. The important thing here is I have a course of action. I plan to implement first without custom RegionAdapter and walk into the Prism code to see if I can find the underlying cause. I'll let you know my findings.
Thanks,
Paul from Minneapolis
We have an app built in Silverlight with Prism, and I'm now considering using the RadDocking Control.
Paul, did you complete a Region Adapter successfully? How long did it take? Any pointers/gotchas (don't suppose you can share your code)?
Thanks
Mark
I wrote a couple of Region Adapters fairly quickly (a day or two) but wasn't able to fully test them as I'm still in design for the overall project. Over the next three months, I'll be building a working prototype and I'll have to get them working soon as the docking control is key to our current UI framework.
Regards,
Paul from Minneapolis
Thank you for sharing you prism experience with us. Recently we blogged about how to create a custom prism adapter in case you want to use the RadDocking control and combine with the Prism framework. You can check the Miroslav's blog post, demonstrating some useful techniques.
Greetings,
Kaloyan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Maybe you can forward my question to Miroslav if you're not sure of the answer..
I looked at the custom Region Adapter Miroslav built. What I find interesting is that he is using a radPane for both the Document Host and the normal Docking control. I thought the Document Host needed a radDocumentPane ... does radDocumentPane inherit from radPane and that's why it works?
I need to dynamically add both radPanes and radPaneDocuments at runtime. This is based upon a lookup to a web service to see what modules the user has been granted access to and then load them.
Note that I haven't tested this thoroughly and will be in the coming week.
My custom Region adapter tries to handle both radPanes and radPaneDocuments types by branching on the value of the Tag property from the incoming module control (an ugly workaround I know). For example, the Add action code block is as thus:
string ModuleTag = CurrentElement.Tag.ToString();
UserControl CurrentElementAsUserControl = CurrentElement as UserControl;
string[] paramModule = ModuleTag.Split(';');
switch (paramModule[0])
{
case "multipane": //pane gets added to existing RadPanegroup
RadPane PaneToAdd = new RadPane();
//embed the content
PaneToAdd.Content = CurrentElementAsUserControl;
//make sure any data bindings are maintained
PaneToAdd.DataContext = CurrentElementAsUserControl.DataContext;
regionTarget.AddItem(PaneToAdd,
DockPosition.Left);
break;
case "docpane": //pane gets added to existing RadPaneGroup inside of document host
RadDocumentPane DocPaneToAdd = new RadDocumentPane();
//embed the content
DocPaneToAdd.Content = CurrentElementAsUserControl;
//make sure any data bindings are maintained
DocPaneToAdd.DataContext = CurrentElementAsUserControl.DataContext;
regionTarget.AddItem(DocPaneToAdd,
DockPosition.Left);
break;
default:
//unknown type of module to embed
break;
}
Also note that if the module has existing data bindings they need to be maintained via assignment of the DataContext property.
Does this look sane to you?
Regards,
Paul from Minneapolis
Regards,
Miroslav Nedyalkov
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Thanks for the prompt reply. And thanks for the suggestions.
My implementation of Prism is more aggressive than the normal...I'm not placing the same views into the regions every time. Upon launch I check a WCF service to validate the user in the system, then I return back a list of modules that user has access for (which becomes the catalog). Then, upon first use, I place the view modules into a default layout. The users can modify the layout via a layout preferences dialog that the user can place their views in the appropriate panes and save the layout (both back to the wcf service and to local isolated storage). Then the next time they load, I restore that layout with the views in that positions.
What I'm shooting for is the ability for the application admins to grant user access to modules and load them at run-time. This is because I have users with different needs and requirements.
Thanks again,
Paul from Minneapolis
I have some fundamental questions using Prism with the docking control. In Miroslav's example the radPane is used to insert into the radPaneGroups regions which static.
In a proof of concept I built for the customer using SketchFlow and the radDocking control, they have multiple module apps (Views) they'd like to have loaded at run-time.
I have three types of regions:
- a radPaneGroup docked top as a region that I can dynamically add the radPanes as needed
- a radPaneGroup nested within the radDocumentHost / radSplitContainer. I add radPanes to this as needed as well.
- a left and a right radSplitContainer that is a region that I can dynamically add a radPane, wrapping it in its own radPaneGroup on the fly inside the RegionAdapter.
The first two types can be handled by the radPaneGroup region adapter.
In the third region type, they like the ability to treat each tool with it's own pin and dock it to the side as a Auto-hide tab or display it as a docked pane (in the radSplitContainer). A main desire is that, upon app startup, determine what tools (as app modules) the user has access to and load them into their own radPaneGroup on the left or right (as tabs). For this I will hit a WCF web service to get the user's catalog info from a database (an application admin will have a screen to assign/remove user permissions to the various app modules).
Do you anticipate problems with trying to make the radSplitContainer a region? I've debated having my app modules have as the top-level element as either:
- radPaneGroups or
- radPanes and dynamically wrap/unwrap them with radPaneGroups on the fly which one seems the better approach to you?
I've created a region adapter with the following class defintion:
public
class RadSplitContainerRegionAdapter : RegionAdapterBase<RadSplitContainer>
Another question: it'd be nice if the docking control save/restore layout would handle the layout state of all these dynamic app modules, but I haven't gotten to where I can try it yet. Would you think it would still function under this approach or should I roll my own save/restore functionality (region position and docking state of the various modules)?
i'm looking for your gut answers on this, don't take the time to proof this out ... unless you really feel you must. ;)
Thanks,
Paul from Minneapolis
All the best,
Miroslav Nedyalkov
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
For Prism-based applications especially, this is a good idea...
"We may consider adding methods for adding panes in a SplitContainer that will add groups automatically and mark the group as auto generated and this group will be recycled automatically when not needed any more. This is already done for the groups that are created when you drag and drop panes."
This simplifies things for folks like me who are trying to provide a reusable application framework for their organization. It then becomes a single UI interface specification for which to create app modules: they only need to buy the radControls, wrap it in a radPane and focus on the specifics of their implementation.
Thanks again. I appreciate your quick response,
Paul from Minneapolis
Regards,
Miroslav Nedyalkov
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
I bumped my head against this problem - ie you cannot use view injection when using the RadPaneGroup within a DocumentHost, which I really need to do.
I found the answer to doing this here;
http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=51602
What you need to do is expose the IRegionManager as a property on the Shell or the presentation model backing the Shell, then bind to it. Your DocumentHost should look as follows;
<
telerikDocking:RadDocking.DocumentHost>
<telerikDocking:RadSplitContainer>
<telerikDocking:RadPaneGroup x:Name="RadPaneGroupDockingAreaRegion" Regions:RegionManager.RegionName="DockingAreaRegion" Regions:RegionManager.RegionManager="{Binding Path=RegionManager}" />
</telerikDocking:RadSplitContainer>
</telerikDocking:RadDocking.DocumentHost>
You should now be able to use the region with view injection.
Hope that helps some folks
Zack
Thank you for your suggestion! We were able to fix the issue for WPF, but unfortunately the problem still exists in Silverlight. Your work-around will help for sure. I updated your Telerik points.
Just one comment - as Prims is walking the Visual tree, you could put the binding only to the top-level RadSplitContainer in the DocumentHost (that is directly set to the DocumentHost property). This way all the regions in the DocumentHost will be able to find their region - the region of the top-level RadSplitContainer in the DocumentHost area.
Regards,
Miroslav Nedyalkov
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
I attached a project reference to the Prism libraries and it seems that the RadPane control is never firing the "Loaded" event for controls that are dynamically created at runtime. Prism relies on this event so that it can create the prism regions on demand. All other controls are firing this "Loaded" event anytime I am doing this (for example, I dynamically create an RadOutlookBarGroup and add some content area in it as a prism region and it works just fine). I would say there is something wrong in the RadPane class but I am not sure where.
All the controls are firing their loaded events when they appear in the visual tree. If there is only one pane in a RadPaneGroup it hides its tab strip area (where the panes are displayed) and the pane never gets shown. On the other hand its content gets added to the visual tree and its loaded event is fired. If you have more than one pane in a pane group, the loaded event only of the selected pane will be fired, because the content of all other panes is actually not visible (a similar thing happens when you use tab control). When the user selects another pane, its content gets added to the visual tree and the content of the previous one is removed from it.
Hope this information is helpful!
About the problem you are experiencing - you said that you are attaching a project, but unfortunately there is no attachment. Could you please open a support ticket and send the project you mentioned (you cannot attach .zip files in a forum thread)? This will help up find what the problem is and better assist you to resolve it.
Sincerely yours,Miroslav Nedyalkov
the Telerik team
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 Public Issue Tracking system and vote to affect the priority of the items.
A quick fix for this is explicitly setting the RegionManager property on the DocumentHost in the View's constructor like this:
_documentHost.SetValue(RegionManager.RegionManagerProperty, regionManager); |
Unity can provide the region manager by adding it as a parameter to the constructor.
Cheers,
Justin
I was trying to use the method of Regions:RegionManager.RegionManager="{Binding Path=RegionManager}" as described in in one of the posts but could not get it right. Instead I'm getting an error on Shell Initialization :
"Invalid attribute value {Binding Path=(RegionManager)} for property RegionManager.RegionManager."
Can anyone help me with this issue. I need urgent solution to it. Is there a sample I can refer to, to resolve my problem?
Did you try the work-around provided by Justin?
All the best,Miroslav Nedyalkov
the Telerik team
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 Public Issue Tracking system and vote to affect the priority of the items.
Thanks in advance.
<telerikDocking:RadDocking x:Name="_mainDock" Grid.Row="1"> |
<telerikDocking:RadDocking.DocumentHost> |
<telerikDocking:RadSplitContainer x:Name="_documentHost" telerikDocking:RadDocking.FloatingSize="1000,700"> |
... |
</telerikDocking:RadSplitContainer> |
</telerikDocking:RadDocking.DocumentHost> |
<telerikDocking:RadSplitContainer InitialPosition="DockedLeft"> |
... |
</telerikDocking:RadSplitContainer> |
<telerikDocking:RadSplitContainer InitialPosition="DockedBottom"> |
... |
</telerikDocking:RadSplitContainer> |
</telerikDocking:RadDocking> |
And here is the example code in the codebehind file:
public partial class Shell : UserControl |
{ |
public Shell(IRegionManager regionManager) |
{ |
InitializeComponent(); |
_documentHost.SetValue(RegionManager.RegionManagerProperty, regionManager); |
} |
... |
} |
Hopefully that makes it clearer for you...
I've converted this solution into an xbap solution. The mainregion is not being loaded into the regionmanager and throws a region not found exception while the code is exactly the same as the desktop one which works perfectly. Am I missing something? Any help will be appreciated
It throws the following exception:
System.Windows.Markup.XamlParseException occurred
Message='The invocation of the constructor on type 'RadDockingAndPRISM_XBAP.Shell' that matches the specified binding constraints threw an exception.' Line number '5' and line position '4'.
Source=PresentationFramework
LineNumber=5
LinePosition=4
StackTrace:
at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
InnerException: Microsoft.Practices.Composite.Modularity.ModuleInitializeException
Message=An exception occurred while initializing module 'ModuleB'.
- The exception message was: The region manager does not contain the MainRegion region.
- The Assembly that the module was trying to be loaded from was:ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Check the InnerException property of the exception for more information. If the exception occurred while creating an object in a DI container, you can exception.GetRootException() to help locate the root cause of the problem.
Source=Microsoft.Practices.Composite
ModuleName=ModuleB
StackTrace:
at Microsoft.Practices.Composite.Modularity.ModuleInitializer.HandleModuleInitializationError(ModuleInfo moduleInfo, String assemblyName, Exception exception)
at Microsoft.Practices.Composite.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo)
at Microsoft.Practices.Composite.Modularity.ModuleManager.InitializeModule(ModuleInfo moduleInfo)
at Microsoft.Practices.Composite.Modularity.ModuleManager.LoadModulesThatAreReadyForLoad()
at Microsoft.Practices.Composite.Modularity.ModuleManager.LoadModuleTypes(IEnumerable`1 moduleInfos)
at Microsoft.Practices.Composite.Modularity.ModuleManager.LoadModulesWhenAvailable()
at Microsoft.Practices.Composite.Modularity.ModuleManager.Run()
at Microsoft.Practices.Composite.UnityExtensions.UnityBootstrapper.InitializeModules()
at Microsoft.Practices.Composite.UnityExtensions.UnityBootstrapper.Run(Boolean runWithDefaultConfiguration)
at Microsoft.Practices.Composite.UnityExtensions.UnityBootstrapper.Run()
at RadDockingAndPRISM_XBAP.Shell..ctor() in E:\Carinthian.Blue\Concepts\DockingAndPrism\RadDockingAndPRISM_XBAP\Shell.xaml.cs:line 12
InnerException: System.Collections.Generic.KeyNotFoundException
Message=The region manager does not contain the MainRegion region.
Source=Microsoft.Practices.Composite.Presentation
StackTrace:
at Microsoft.Practices.Composite.Presentation.Regions.RegionManager.RegionCollection.get_Item(String regionName)
at ModuleB.ModuleB.Initialize() in E:\Carinthian.Blue\Concepts\DockingAndPrism\ModuleB\ModuleB.cs:line 21
at Microsoft.Practices.Composite.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo)
InnerException:
<
telerikDocking:RadDocking
x:Name
=
"radDocking1"
Grid.Row
=
"1"
AllowUnsafeMode
=
"True"
cal:RegionManager.RegionManager
=
"{Binding Path=RegionManager}"
>
<
telerikDocking:RadDocking.DocumentHost
>
<
telerikDocking:RadSplitContainer
x:Name
=
"_documentHost"
>
<
telerikDocking:RadPaneGroup
x:Name
=
"radPaneGroup"
cal:RegionManager.RegionName
=
"{x:Static infra:RegionNames.MainRegion}"
cal:RegionManager.RegionManager
=
"{Binding Path=RegionManager}"
>
<
telerikDocking:RadDocumentPane
Title
=
"Home"
CanFloat
=
"False"
CanUserClose
=
"True"
/>
</
telerikDocking:RadPaneGroup
>
</
telerikDocking:RadSplitContainer
>
</
telerikDocking:RadDocking.DocumentHost
>
<
telerikDocking:RadSplitContainer
InitialPosition
=
"DockedLeft"
>
<
telerikDocking:RadPaneGroup
>
<
telerikDocking:RadPane
Header
=
"Section"
HeaderTemplate
=
"{StaticResource SectionHeaderTemplate}"
IsPinned
=
"False"
CanUserClose
=
"True"
cal:RegionManager.RegionName
=
"LeftRegion"
/>
</
telerikDocking:RadPaneGroup
>
</
telerikDocking:RadSplitContainer
>
<
telerikDocking:RadSplitContainer
InitialPosition
=
"DockedRight"
>
<
telerikDocking:RadPaneGroup
>
<
telerikDocking:RadPane
HeaderTemplate
=
"{StaticResource HelpHeaderTemplate}"
Header
=
"Help"
CanUserClose
=
"True"
CanFloat
=
"True"
IsPinned
=
"False"
cal:RegionManager.RegionName
=
"RightRegion"
/>
</
telerikDocking:RadPaneGroup
>
</
telerikDocking:RadSplitContainer
>
</
telerikDocking:RadDocking
>
I am loading a view called View1 into the MainRegion as a doc pane.
<
telerikDocking:RadPane
x:Class
=
"View1"
xmlns:telerikDocking
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking"
xmlns:cal
=
"http://www.codeplex.com/CompositeWPF"
xmlns:x
=
"http://schemas.microsoft.com/winfx/2006/xaml"
Header
=
"Search"
x:Name
=
"SearchTestView"
>
<
Grid
>
<
TextBlock
>testing 123</
TextBlock
>
</
Grid
>
</
telerikDocking:RadPane
>
This all works but the problem lies in when I close the docpane (tab) there are issues reactivating it using the code below. It works the first time, but if I close the docpane again, they code runs without error but the view does not display..
string
viewName1 =
"SearchTestView"
;
IRegion detailsRegion1 = _regionManager.Regions[
"MainRegion"
];
object
view1 = detailsRegion1.GetView(viewName1);
if
(view1 ==
null
)
{
view1 = _container.Resolve<View1>();
detailsRegion1.Add(view1, viewName1);
}
detailsRegion1.Activate(view1);
Any help would be most appreciated. Thanks.
We are not aware of such problem. Could you please give us more information about your scenario? Why do you need to close one and same pane several times ? Also, if you send us a running example it would be very helpful in further pinpointing the problem.
George
the Telerik team
I can't find the post that helped solve my solution right now but it seems that the PRISM framework is not handling the view name properly. The post that I read described that the GetView prism function was not working correctly in actually finding the view name (x:Name).
detailsRegion1.GetView("MyView");
This code will return null even though I have specified x:Name="MyView" in my prism view (RadDocumentPane).
This could be more elegant code but for now this is how I got my menu button to re-load /open a RadDocumentPane view.
bool found = false;
foreach (RadPane pane in detailsRegion.ActiveViews)
{
if (pane.Name == viewName)
{
found = true; break;
}
}
if (!found)
{
object view = _container.Resolve<
AssessmentSearchView
>();
detailsRegion.Add(view, viewName);
}
For anyone interested (since I cound't find an example) here is how I remove the view when the user clicks the close button on the RadDocumentPane. This code is in my shell view where all the the rad docking controls are (also not that elegant right now).
private void RadDocking_Close(object sender, Telerik.Windows.Controls.Docking.StateChangeEventArgs e)
{
IRegion MainRegion = _RegionManager.Regions["MainRegion"];
foreach (var pane in e.Panes)
{
foreach (RadPane view in MainRegion.ActiveViews)
{
if (pane.Name == view.Name)
MainRegion.Remove(view);
}
}
}
So ...my initial problems are somewhat solved and seem to work but now I have a new problem which seems to be described in this logged issue and resolved but unscheduled.
http://www.telerik.com/community/forums/wpf/docking/binding-fails-after-switching-between-tabbed-document-and-floating-mode-radpane.aspx
http://www.telerik.com/support/pits.aspx#/public/wpf/3952
I had this RadPaneGroupRegionAdapter working fine...then i started moving my reference dlls around...now I evidently moved somehting i shouldnt have and im getting the following errors on the line
regiontarget.Items.Add(item);
Items is the red squiggly error and it says:
ItemCollection ItemsControl.Items
C# Unknown member 'Items' of Telerik.Windows.COntrols.RadPaneGroup
similarly for parent
unknown member "Parent" of Telerik.Windows.Controls.radPane"
i hate reference crap!!
OK loaded it on my laptop and it now has the following error on RadPaneGroup within the " RegionAdapterBase<RadPaneGroup>
stating that module "System.Windows" must be referenced
ohhh help i do dislike references
Please, clean the project, remove the references, added them again, clean again and rebuild the project. Make sure you have added the following references in order to use the RadDocking controls:
- Telerik.Windows.Controls
- Telerik.Windows.Controls.Navigation
- Telerik.Windows.Controls.Docking
I hope this helps.
George
the Telerik team
I am experiencing the same issue as discussed on http://compositewpf.codeplex.com/discussions/60215?ProjectName=compositewpf
Unfortunately the above link does not provide a solution.
From what I understand the RegionManager walks the visual tree discovering regions that have been defined, however, it cannot access any controls located within the DocumentHost.
Is it possible to define a region within a DocumentHost while using Prism with DI?
Thanks heaps.
We area aware of such problem with the regions, defined in the DocumentHost. Could you please specify do you use PRISM Unity or PRISM MEF?
George
the Telerik team
Thanks for the reply - we are using Unity
Cheers
Chris
We are using Prism with Unity. Is there a way to make this work?
Thanks heaps,
Patrick.
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 RegionManager.SetRegionManager method to register the pane group as region.
George
the Telerik team
We follow a different approach where the Shell manages all the interaction between it's 3rd party controls and Regions. Module's "loosely" register themselves into the Shell by invoking a custom CompositePresentationEvent. So, essentially, we never register "regions" with the DocumentHost. The Shell takes care of creating and cleaning up the different Document Windows by creating a new Content element that the Module's multiple UIs get plugged into. The modules know nothing about this and don't care.
Hint / Example:
eventAggregator.GetEvent<ShellViewRegistrationEvent>().Publish(new ShellViewActivationEventArgs(...));
In our framework, we can actually have other modules that use different 3rd party tools that know absolutely nothing about Telerik but at the same time can plug right into the Shell (again, because the Shell is driving everything). Suffice it to say, I have yet to develop ANY custom RegionManagers for Telerik controls. We have also been able to port our applications over to MEF fairly easily without affecting large chunks of code in the Modules. Basically, only the Shell changes.
One other question... how can you access the parent of a RadSplitContainer which is located within a DocumentHost?
When a RadSplitContainer is located within a DocumentHost, the Parent property is null.
Thanks heaps,
Patrick.
The workaround I use for this (I've ran into the same issue) is to store a reference to the RegionManager in the shell's view model then bind it like this:
ShellView.cs
<
telerikDocking:RadDocking
>
<
telerikDocking:RadDocking.DocumentHost
>
<
telerikDocking:RadSplitContainer
x:Name
=
"CenterContainer"
>
<
telerikDocking:RadPaneGroup
x:Name
=
"MainRegion"
rgn:RegionManager.RegionManager
=
"{Binding RegionManager}"
rgn:RegionManager.RegionName
=
"{StaticResource MainRegion}"
>
</
telerikDocking:RadPaneGroup
>
</
telerikDocking:RadSplitContainer
>
</
telerikDocking:RadDocking.DocumentHost
>
</
telerikDocking:RadDocking
>
ShellViewModel.cs
public
class
ShellViewModel : NotificationObject
{
public
IRegionManager RegionManager {
get
;
private
set
; }
public
ShellViewModel(IRegionManager regionManager)
{
RegionManager = regionManager;
}
}
Yes it's incomplete, I'm defining all string constants in code then add them as static resources at runtime via merged dictionaries. Here's how I do it:
Constants class (each app module including shell could have one of these):
public
class
ApplicationData
{
// Shell regions
public
const
string
RegionNavigationTop =
"NavigationRegionTop"
;
public
const
string
RegionNavigationBottom =
"NavigationRegionBottom"
;
public
const
string
RegionMain =
"MainRegion"
;
public
const
string
RegionMenu =
"RegionMenu"
;
public
const
string
RegionFloatingDockRight1 =
"RegionFloatingDockRight1"
;
public
const
string
RegionFloatingDockRight2 =
"RegionFloatingDockRight2"
;
public
const
string
RegionBottomPanel =
"RegionBottomPanel"
;
}
An extension class that takes constants and adds them as static resources:
public
static
class
CommonExtensions
{
/// <summary>
/// Builds a dictionary at runtime with string constants from the given type and merges it into the global application dictionary.
/// </summary>
/// <param name="Type"></param>
public
static
void
RegisterDictionaryLiterals(
this
Type Type)
{
var literals = Type.GetFields().Where(f =>
f.IsPublic && f.IsLiteral &&
(f.FieldType.Equals(
typeof
(
string
)) || f.FieldType.Equals(
typeof
(
int
)) || f.FieldType.Equals(
typeof
(
double
))));
ResourceDictionary dict =
new
ResourceDictionary();
foreach
(FieldInfo literal
in
literals)
{
dict.Add(literal.Name, literal.GetRawConstantValue());
}
Application.Current.Resources.MergedDictionaries.Add(dict);
}
}
Finally, in every module you register the constants (in ModuleInit.cs ctor or Application_Startup in shell):
typeof
(ApplicationData).RegisterDictionaryLiterals();