Why usercontrols loaded event is not fired - wpf

I have a user control. I had this situations again some times but could always fix it by using the "New() contructor". But I still wonder what I am doing wrong because the load event has to be fired if control was loaded!
Here is some code:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:OUTPUT___VideoContent"
Title="OUTPUT - VideoContent" Height="350" Width="525" Icon="/OUTPUT%20-%20VideoContent;component/Images/VideoContent.png">
<Grid x:Name="LayoutRoot">
<Grid x:Name="VideoGrid">
<my:ucVideoPresenter x:Name="VideoPresenter1"/>
<TextBlock x:Name="txtInfo" Visibility="Collapsed" />
</Grid>
</Grid>
</Window>
and in the usercontrol, the load event is declared on WPF or codebehing without any success!

This is because an exception is being thrown in the 'Loaded' eventhandler. The exception may be occurring as a result of a mixed mode assembly or some other exception that is "user handled", and the WPF framework is catching it (unknown to the debugger). This causes the debugger not to break when a breakpoint is set within the Loaded method.
To make sure you can see exactly what error is occurring:
In VS2010 go to Debug | Exceptions.
Tick "Thrown" exception radio boxes for the exceptions that may be applicable in your case.
Re-run the app and VS2010 should break on the exception that is being thrown in the event handler.
Debug according to a now known exception.

Does your UserControl constructor still make a call InitializeComponent(), without this, it will not build up its visuals and the Loaded event may not fire.

Related

Value cannot be null. Parameter name: hostNameOrAddress

I have a WPF application and am suddenly getting the error
Value cannot be null. Parameter name: hostNameOrAddress
With this error the program will still run. When I remove the datacontext from the window this error goes away. In this window my datacontext is my MainViewModel. I tried removing the MainViewModel from the assembly and adding it back in thinking that might solve the problem but to no avail. Does anyone have any thoughts on why this could be happening. Note: I am using MahApps.Metro.
<controls:MetroWindow x:Class="DatalogConversion.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DatalogConversion"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:helper="clr-namespace:DatalogConversion.Helper"
Height="auto"
Width="325"
SizeToContent="Height">
<controls:MetroWindow.DataContext>
<local:MainViewModel/>
</controls:MetroWindow.DataContext>
I was using an attached property to call a method in my view model when my window was loaded
helper:MvvmBehaviors.LoadedMethodName="OnWindowLoaded"
I didn't realize this at the time but the problem was I was calling a service from the method and it was breaking the designer. To fix the problem I inserted a guard clause in the OnWindowLoaded method to fix the problem.
if (DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject())) return;

Why does ServiceLocator.Current.GetInstance cause UserControls to not work at design-time?

I'm having an issue where if I call ServiceLocator.Current.GetInstance(type) anywhere in my project, it causes UserControls throughout my project to stop instantiating within other controls at design-time in Visual Studio. These controls work fine at run-time however.
It is reproducible by creating a simple WpfApplication with the following 3 classes. The first build will succeed, and the designer will show fine. If you rebuild, however, it throws the error and the designer stops instantiating the UserControls within other controls. Because of this behavior, it seems like a Visual Studio bug, but I'm not sure.
When uncommented, the #GetInstance(Type type) function of ServiceLocator causes an Error in the error list Cannot locate resource 'controls/test.xaml and the designer shows an error Cannot create an instance of "Test" where the Test UserControl should be. When commented, there are no errors.
Test xaml class.
<UserControl x:Class="XamlTest.Controls.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid>
<Label Content="Test"/>
</Grid>
</UserControl>
MyView xaml class. (uses Test)
<UserControl x:Class="XamlTest.Views.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mycontrols="clr-namespace:XamlTest.Controls"
mc:Ignorable="d">
<Grid>
<mycontrols:Test/>
</Grid>
</UserControl>
A class unrelated to the UserControls that uses ServiceLocator.Current.GetInstance(type);.
using Microsoft.Practices.ServiceLocation;
namespace XamlTest.SomeClasses
{
class SomeClass
{
public void SomeFunction()
{
// Causes Test xaml class to not instantiate at design time within MyView.
// Does not matter what parameters you give the function.
// Notice this class isn't even associated with any other class,
// and is never called, but it still causes problems.
ServiceLocator.Current.GetInstance(null);
}
}
}

windowsformhost cant load a usercontrol from another dll

So I have a dll from another project which contains many useful classes and controls for me (lets call it foo.dll). I'm making an WPF app. I need to use some of them in my app. I created my usercontrol for windows forms and referenced UserControlForMe from foo.dll. It's shown, all good. Now I want to insert my usercontrol into a wpf form. It looks like this:
<UserControl x:Class="FlatRectangular_Profile.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:uc="clr-namespace:FlatRectangular_Profile.UC"
Height="2093" Width="717">
<Grid Name="grid">
<WindowsFormsHost>
<uc:WindowsFormsProfManual ></uc:WindowsFormsProfManual>
</WindowsFormsHost>
</Grid>
</UserControl>
But here I get an error "cant load type UserControlForMe from foo.dll". No info on that error. Again, UserControlForMe loads in WindowsFormsProfManual. All these is going on in one class library. I referenced everything that foo.dll needed.
No idea how what to do next. I also tried to load it in code in usercontrol.loaded event, but it fails too, and shows stacktrace which leads to the constructor of the UserControlForMe.
I guess you'll have to add the assembly to your namespace import to point your application in the right direction:
xmlns:uc="clr-namespace:FlatRectangular_Profile.UC;Assembly=MyDLL"
I found a workaround since I cant get why it is not working. If I load a UserControlForMe from foo.dll directly to the windowsformhost, it works. But if there is a "buffer" dll, it works in this dll, but doesnt open in futher window. Also I add a UserControlForMe programmatically to a windowsformhost.

Setting design time DataContext on a Window is giving a compiler error?

I have the following XAML below for the main window in my WPF application, I am trying to set the design time d:DataContext below, which I can successfully do for all my various UserControls, but it gives me this error when I try to do it on the window...
Error 1 The property 'DataContext' must be in the default namespace or in the element namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. Line 8 Position 9. C:\dev\bplus\PMT\src\UI\MainWindow.xaml 8 9 UI
<Window x:Class="BenchmarkPlus.PMT.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:UI="clr-namespace:BenchmarkPlus.PMT.UI"
xmlns:Controls="clr-namespace:BenchmarkPlus.PMT.UI.Controls"
d:DataContext="{d:DesignInstance Type=UI:MainViewModel, IsDesignTimeCreatable=True}"
Title="MainWindow" Height="1000" Width="1600" Background="#FF7A7C82">
<Grid>
<!-- Content Here -->
</grid>
</Window>
I needed to add the mc:Ignorable="d" attribute to the Window tag. Essentially I learned something new. The d: namespace prefix that Expression Blend/Visual Studio designer acknowledges is actually ignored/"commented out" by the real compiler/xaml parser!
<Window
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
/>
The following was taken from
Nathan, Adam (2010-06-04). WPF 4 Unleashed (Kindle Locations 1799-1811). Sams. Kindle Edition.
Markup Compatibility
The markup compatibility XML namespace (http://schemas.openxmlformats.org/markup-compatibility/2006, typically used with an mc prefix) contains an Ignorable attribute that instructs XAML processors to ignore all elements/attributes in specified namespaces if they can’t be resolved to their .NET types/members. (The namespace also has a ProcessContent attribute that overrides Ignorable for specific types inside the ignored namespaces.)
Expression Blend takes advantage of this feature to do things like add design-time properties to XAML content that can be ignored at runtime.
mc:Ignorable can be given a space-delimited list of namespaces, and mc:ProcessContent can be given a space-delimited list of elements. When XamlXmlReader encounters ignorable content that can’t be resolved, it doesn’t report any nodes for it. If the ignorable content can be resolved, it will be reported normally. So consumers don’t need to do anything special to handle markup compatibility correctly.
Wow, what a pain! Let's hope MS puts in some VS design-time support for x:Bind.
We to be able to use the VS designer but also be able to switch easily to x:Bind instead of Binding. Here's what I did:
In my View, I added a property to get my ViewModel. This makes sense because x:Bind paths are relative to the Page (i.e. the View object).
In my Page XAML, I added the following to the <Page ... > at the top of the XAML:
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyView, IsDesignTimeCreatable=False}"
DataContext="{x:Bind}"
This way, the Page's actual data context is set to the Page itself due to the {x:Bind}. That's because x:Bind is relative to the Page and there is no path given.
At the same time, due to the d:DataContext line, the VS designer reflects on the MyView class (without creating an instance) for the purpose of the VS designer interaction. This lets VS design from MyView, where you can then scroll down to the ViewModel property, expand it and select the item that you want to bind to.
When you do all that, the VS designer will create a Binding statement whose path is relative to the View, i.e. it happens to be exactly the same as the path that x:Bind expects. So, if you want to switch to x:Bind later on, you can just search and replace all "{Binding" with "{x:Bind".
Why do we even need the d:DataContext line to tell VS what class to look at? Good question, since you would think that VS could figure out the very next line sets the DataContext to the Page, using DataContext={x:Bind}. Go ahead and try it, it does not work and neither does it work if you change x:Bind to Binding relative to self.
Hopefully this situation will get cleaned up by MS !!
If you are not tooo fussy on the data have a look at the sample data found in xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
You use it like this...
<ItemsControl ItemsSource="{Binding Path=Report.Audit.Data}" d:ItemsSource="{d:SampleData}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
it then renders the items control with a few rows of data
I've solved the problem adding d:DataContext="{d:SampleData}" in the component definition (UserControl or Window).
<UserControl x:Class="TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TestApp.Views"
DataContext="{Binding TestViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:SampleData}"
>

Handle exceptions with WPF and MVVM

I am attempting to build an application using WPF and the MVVM pattern. I have my Views being populated from my ViewModel purely through databinding. I want to have a central place to handle all exceptions which occur in my application so I can notify the user and log the error appropriately.
I know about Dispatcher.UnhandledException but this does not do the job as exception that occur during databinding are logged to the output windows. Because my View is databound to my ViewModel the entire application is pretty much controlled via databinding so I have no way to log my errors.
Is there a way to generically handle the exceptions raised during databinding, without having to put try blocks around all my ViewModel public's?
Example View:
<Window x:Class="Test.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestView" Height="600" Width="800"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<StackPanel VerticalAlignment="Center">
<Label Visibility="{Binding DisplayLabel, Converter={StaticResource BooleanToVisibilityConverter}}">My Label</Label>
</StackPanel>
</Window>
The ViewModel:
public class TestViewModel
{
public bool DisplayLabel
{
get { throw new NotImplementedException(); }
}
}
It is an internal application so I do not want to use Wer as I have seen previously recommended.
The Binding implementation is designed to be fault tolerant and so it catches all the exceptions. What you could do is to activate the following properties in your bindings:
ValidatesOnExceptions = true
NotifyOnValidationError = true
See also the MSDN.
This causes to raise the attached Error property on the bound control.
However, this infrastructure is designed for validating the user input and show validation messages. I’m not sure if this is what you are doing.

Resources