Prism Regions UpdateRegionsException - wpf

I have an application which registers 2 regions with the region manager, 1 is a content control and the other a custom control. Both are fine when running the application until I tried using an RDP session. If I disconnect from the remote machine running the application and then reconnect the RDP with the application left running I get an exception that the custom control is already registered. Both have the RegionMeneberLifetime set to false.
The content control is added 1st as
<ContentControl x:Name="MainRegion" Panel.ZIndex="0"
regions:RegionManager.RegionName="{x:Static sharedInterfaces:RegionNames.MainWorkspaceRegion}"
regions:RegionManager.RegionManager="{Binding RegionManager}"/>
and then the custom control
<controls:PopUpContainer regions:RegionManager.RegionName="{x:Static sharedInterfaces:RegionNames.PopupRegion}"
regions:RegionManager.RegionManager="{Binding RegionManager}"/>
The custom control inherits from ContentControl.
The exception thrown is
Message:
An exception occurred while creating a region with name
'MainWorkspaceRegion'. The exception was:
Microsoft.Practices.Prism.Regions.UpdateRegionsException: An exception
occurred while trying to create region objects.
- The most likely causing exception was: 'System.Reflection.TargetInvocationException: Exception has been
thrown by the target of an invocation. --->
Microsoft.Practices.Prism.Regions.Behaviors.RegionCreationException:
An exception occurred while creating a region with name 'PopupRegion'.
The exception was: System.ArgumentException: Region with the given
name is already registered: PopupRegion
It looks like the popupregion has not been disposed and in trying to add it again it blows up. Any suggestions on how I can handle this?

Be shure to add
regions:RegionManager.RegionName="{x:Static sharedInterfaces:RegionNames.PopupRegion}
just once in the whole Application.
If you've got 2 regions with same name, you will get this exception.
(I've got not enough reputation for comment)

Found a work around.
The view does not register the controls with the regions manager, instead it is done in the code behind.
The view adds the controls and gives them a name
<ContentControl x:Name="MainRegion" Panel.ZIndex="0"/>
<controls:PopUpContainer x:Name="PopupControl" Grid.ColumnSpan="2"/>
The code behind adds the regions when a datacontext change event occurs
private void ShellView_OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var dataContext = DataContext as ShellViewModel;
if (dataContext != null)
{
if (dataContext.RegionManager.Regions.ContainsRegionWithName(RegionNames.PopupRegion))
{
dataContext.RegionManager.Regions.Remove(RegionNames.PopupRegion);
}
RegionManager.SetRegionName(PopupControl, RegionNames.PopupRegion);
RegionManager.SetRegionManager(PopupControl, dataContext.RegionManager);
if (dataContext.RegionManager.Regions.ContainsRegionWithName(RegionNames.MainWorkspaceRegion))
{
dataContext.RegionManager.Regions.Remove(RegionNames.MainWorkspaceRegion);
}
RegionManager.SetRegionName(MainRegion, RegionNames.MainWorkspaceRegion);
RegionManager.SetRegionManager(MainRegion, dataContext.RegionManager);
}
}

Related

Converting WPF application to UserControl for use in WinForms application via ElementHost

I'm trying to convert this WPF application to WPF UserControl so I could use it in WinForms application via ElementHost. I'm new to WPF and have never even touched it prior to this attempt so I might be going about it completely the wrong way.
I got the UserControl project to compile, however, my StaticResources get underlined in VS with message "The resource 'x' could not be resolved". I've tried moving the xamls with the needed x:Key elements up one level (the same level as the UserControl Dijagram.xaml), but it still cannot resolve them.
In the WinForms app, when trying to add the UserControl through designer by selecting hosted content in ElementHost tasks I get the following error:
An error occured trying to create an object of type
'DijagramLC.Dijagram'. Make sure the type has a default constructor.
(even though default constructor exists).
However, if I add it in codebehind, like this:
wpfUserControl = new Dijagram();
elementHost1.Child = wpfUserControl;
Controls.Add(elementHost1);
the code compiles but throws this runtime error: "System.Windows.Markup.XamlParseException: 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '20' and line position '4'. ---> System.Exception: Cannot find resource named 'MyToolbar'. Resource names are case sensitive."
I've tried with and without App.xaml and adding ResourceDictionary elements for problematic xamls, but basically, I have no idea what I'm doing :)
I've uploaded the code to my SkyDrive and would really appreciate it if someone could take a look and tell me what I'm doing wrong:
https://skydrive.live.com/redir.aspx?cid=21be1f8e850e85cc&resid=21BE1F8E850E85CC!353
I hate jumping in blindly to new techonoly like this, but I have had no choice this time, and need to know if my requirement is even achievable this way.
You are probably getting the error because you use resources from a resource dictionary which is not loaded. Loading a resource dictionary in the hosting application will probably solve the issue:
// When hosting a WPF usercontrol inside an element host,
// application resources are not loaded, so we need to load them manually.
var resources = new ResourceDictionary
{
Source = new Uri("/UNIT4.MKB.GUI.XAML.Dashboard.Resources;component/resources.xaml", UriKind.Relative)
};
// Check for null reference
if (Application.Current != null)
{
//Merge the loaded ResourceDictornairy with the dummy application Resources.
Application.Current.Resources.MergedDictionaries.Add(resources);
}
The problem is, you need THE default constructor like this:
public CreatedPollsUC()
{
InitializeComponent();
}
If you have any other code in the constructor, the error occures:
public CreatedPollsUC()
{
InitializeComponent();
// ... more code
}
So if you want to use further code in the constructor, you need to apply the control first to the element host. Then you can edit the constructor.

Exception causing break during debug instead of validation for binding in Silverlight on Windows Phone

I'm trying to implement binding validation using Silverlight on Windows Phone, but all I get is the debugger breaking on an unhandled exception instead, and the validation not happening.
I'm following the recommendations from an MSDN article on Data Binding.
Here is what I have tried to do to set it up:
Debug -> Exceptions -> Common Language Runtime Exceptions - User-unhandled is unchecked
On the data template for the ListBoxItem, I declare two-way binding with validations:
<TextBox x:Name="LastReadingValue" Text="{Binding LastReadingValue, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
In the setter I raise an exception if the TextBox data is incorrect:
public string LastReadingValue
{
get
{
return _lastReadingValue;
}
set
{
try
{
double reading = System.Convert.ToDouble(value);
_lastReadingValue = String.Format("{0:0.00}", reading);
}
catch (FormatException fe)
{
throw new Exception("The meter reading must be a number like 7561.41");
}
NotifyOfPropertyChanged("LastReadingValue");
}
}
On the ListBox I declare the handler for the BindingValidationError event:
<ListBox x:Name="NewMeterReadingsListBox" ItemsSource="{Binding Meters}" ItemTemplate="{StaticResource NewMeterReadingDataTemplate}" BindingValidationError="ListBox_BindingValidationError"/>
The handler for the BindingValidationError never gets called:
private void ListBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
Debug.WriteLine("BindingValidationError");
}
Ok - 2nd try at an answer.
A couple of interesting things happened when I tried this myself. I started from the WindowsPhoneDataboundApplication then added a TextBox and validation to the app's ListBox. I'm using the WP Mango Beta 2 tools (not the Beta 2 update from yesterday).
When debugging: if an invalid value is entered I get a debug break and prompt from VS on the throw line says that the exception is unhandled. HOWEVER: the BindingValidationError handler is called fine, the application keeps running and Application.UnhandledException isn't called.
In the _BindingValidationError function the Debug.WriteLine text is often difficult to spot with the other exception text in the output window. If you make it more obvious by forcing a new line you should spot the text:
Debug.WriteLine("\n\n*** BindingValidationError ***\n");
So basically it's working for me, but there are a couple of things to watch out for when debugging.
If you're targetting WP Mango I'd recommend you consider the Silverlight 4 way of doing data validation which doesn't involve throwing and catching exceptions - I agree with Claus insofar as using exceptions is a really ugly way of doing validation. The SL4 alternative involves implementing the IDataErrorInfo and INotifyDataErrorInfo interfaces in your bound class. I haven't tried this approach personally myself though.
Edit:
If you really want to turn off the break on exceptions you can do it from the VS2010 "Debug" menu, "Exceptions" item. Then de-select the exception type you don't want VS to do break on if it is unhandled.
If you create your own custom Exception class just for binding validation and disable the debug break only for that Exception type, then you will be able to have normal VS behaviour for your app's exceptions except when when dealing with binding failures.

Prism regions not displaying registered views

I'm using PRISM in a SilverLight 4 application. I have a problem where views registered to some regions doesn't get displayed.
When loading a module at startup I register some views to regions as follows:
RegionManager.RegisterViewWithRegion("MyRegion1", typeof(IMySubView1));
RegionManager.RegisterViewWithRegion("MyRegion2", typeof(IMySubView2));
I have a view implementing an interface called IMyView, where the xaml have two contentcontrols with regions defined in a grid like this:
<ContentControl Regions:RegionManager.RegionName="MyRegion1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Grid.Row="0" Grid.RowSpan="1"/>
<ContentControl Regions:RegionManager.RegionName="MyRegion2" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Grid.Row="1" Grid.RowSpan="1"/>
I have tried two different methods for adding the view to the main region. Both adds the view and basic elements such as buttons get displayed, but the regions defined in the view does not get filled with associated views.
Method 1:
object obj = _container.Resolve<IMyView>();
IRegion mainRegion = _regionManager.Regions["MainViewRegion"];
IRegionManager scoped = mainRegion.Add(obj, "test", true);
mainRegion.Activate(obj);
// Enabling the following call, it will fail saying the region MyRegion1 does not exist. Feels like it should?
// IRegion myRegion = scoped.Regions["MyRegion1"];
Method 2:
object obj = _container.Resolve<IMyView>();
_regionManager.AddToRegion("MainViewRegion", obj);
_regionManager.Regions["MainViewRegion"].Activate(obj);
It feels like the regions defined in the xaml file doesn't get registered, and because of that the registered views do not get displayed.
The MainViewRegion is defined in the shell in a TabControl as this:
<TabControl Margin="8,0,8,8" Regions:RegionManager.RegionName="MainViewRegion">
Any suggestions on solving my problem will be greatly appreciated!
I'm facing the same problem. The idea is that for whatever reason view injection {mainRegion.Add(obj, "test", true)} for already created regions doesn't show the view. A workaround that worked for me, is to create the region from code, and then inject the view. Something like this:
Microsoft.Practices.Composite.Presentation.Regions.RegionManager.SetRegionManager(headerRegionContainer, _RegionManager);
Microsoft.Practices.Composite.Presentation.Regions.RegionManager.SetRegionName(headerRegionContainer, regionName);
var view = _UnityContainer.Resolve(bag.HeaderViewType);
_RegionManager.Regions[regionName].Add(view);
_RegionManager.Regions[regionName].Activate(view);
Unfortunately for me I can't reach my goal this way, but maybe you can.
Regards,
Levente
After many hours of troubleshooting I found something.
In Composite.Presentation\Regions\RegionManager.cs there is a method called IsInDesignMode. When a region is about to be created this method is called, and if this method returns true the region is not created. See below:
private static void OnSetRegionNameCallback(DependencyObject element, DependencyPropertyChangedEventArgs args)
{
if (!IsInDesignMode(element))
{
CreateRegion(element);
}
}
private static bool IsInDesignMode(DependencyObject element)
{
// Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode.
return DesignerProperties.GetIsInDesignMode(element) || Application.Current == null
|| Application.Current.GetType() == typeof(Application);
}
When our silverlight application starts up and the regions in the shell gets created everything is fine, the Application.Current property is of type "MyName.Shell.App". But when a view gets added after startup, as a response to user input, the Application.Current type is suddenly of type "Application", and thus the IsInDesignMode method returns true and the regions are not created.
If I remove the Application.Current conditions everything works as expected. So the question is, is there something wrong in my application or is there something wrong in the prism source code?
where is your _regionManager coming from ?
Did you write a proper BootStrapper
?
You need to write a class inheriting from MefBootstrapper or UnityBootstrapper (or a custom one if you're not using neither of those IoC/Extension framework) in order to register all your needed types within the IoC container.
could you post the BootStrapper code ?
The problem is gone in Prism version 4.0, I was running Prism version 2.2 when the problem occured.

How to properly use a Subclassed silverlight control?

I created this class where I wanted to override this specific event for the content control.
public class MyContentControl : ContentControl
{
protected override void OnKeyUp(KeyEventArgs e)
{
//do something
//..........
e.Handled = true;
}
}
However when I am using this control in my XAML everything compiles and works fine, but I am getting a runtime exception and I am not sure exactly why? Could someone point me in the right directions....
The exception I get is
XamlParseException
UPDATED (Shows where abouts of the exceptions)
In the XAML I have:
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
and I use it like:
<ctrls:MyContentControl Grid.Column="0" x:Name="_contentControl" VerticalAlignment="Center" HorizontalAlignment="Center" />
Content controls require a default template to be created somewhere (e.g. in generic.xaml). They do not have a matching XAML file like user controls.
If you can provide more information, I can show you how to create an appropriate template.
There are many reasons for this.
To start with. Give the fully qualified namespace.
Instead of
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls"
Use
xmlns:ctrls="clr-namespace:SilverlightProject.CustomControls;assembly=YourAssebmlyName"
If that, doesn't help.
You directly attach your control with the application. Then, enable Debug -> Exceptions. Check Thrown option for the CLR execetion checkbox. You have fair amount of possibility to get to know the cause.

Element is already the child of another element

I get the folowing error in my Silverlight application. But i cant figure out what control it is that is the problem. If i debug it don't break on anything in the code, it just fails in this framework callstack with only framework code. Is there any way to get more information on what part of a Silverlight app that is the problem in this case.
Message: Sys.InvalidOperationException: ManagedRuntimeError error #4004 in control 'Xaml1': System.InvalidOperationException: Element is already the child of another element.
at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.Collection_AddValue[T](PresentationFrameworkCollection`1 collection, CValue value)
at MS.Internal.XcpImports.Collection_AddDependencyObject[T](PresentationFrameworkCollection`1 collection, DependencyObject value)
at System.Windows.PresentationFrameworkCollection`1.AddDependencyObject(DependencyObject value)
at System.Windows.Controls.UIElementCollection.AddInternal(UIElement value)
at System.Windows.PresentationFrameworkCollection`1.Add(T value)
at System.Windows.Controls.AutoCompleteBox.OnApplyTemplate()
at System.Windows.FrameworkElement.OnApplyTemplate(IntPtr nativeTarget)
The XAML for the AutoCompeletBox that is in the context is:
<tk:AutoCompleteBox
x:Name="acName"
Grid.Row="0"
Grid.Column="1"
LostFocus="acName_LostFocus"
Height="20"
Width="80"
HorizontalAlignment="Left"/>
The error is a generic catch-all exception that has many many causes. I've written a debugger utility that can help to identify which part of the XAML is actually causing the error. You can download it from my blog: http://whydoidoit.com/2010/08/30/debug-xaml-element-is-already-the-child-of-another-element/
Your items may be visual elements, instead of data objects.
If you provide the XAML, I can help make sure that is the case.
Usually this error occurs when the said Element is already attached to an existing Parent and somewhere in your code you're attempting to re-parent it (ie via just straight "add" when you in turn must remove the child from the parent first, then Add it to the children etc).
Where specifically the control is failing the above isn't enough info to digest.
Simple and stupid solution:
public class AutoCompleteTextBox : AutoCompleteBox
{
public override void OnApplyTemplate()
{
try
{
base.OnApplyTemplate();
}
catch { }
}
}

Resources