Role of Parameterless constructor in WPF (XAML) - wpf

I've been reading an online tutorial on WPF, there I read a line
"All classes in WPF have parameterless constructors and make excessive usage of properties. That is done to make it perfectly fit for XML languages like XAML."
I examined above words by creating a custom class with one parameterized constructor and encountered error "Type 'custom_class_name' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter."
I just wanted to know a specific detailed reason, how parameterless constructors help achieving this.

The WPF Framework uses the parameter-less constructors to instantiate all of the objects that we define in our XAML pages when it builds the visual tree. If it tries to instantiate an object that does not have a public parameter-less constructor, then you will throw this Exception. If you were to add a parameter-less constructor to your object and try again, then this Exception should disappear.
Please also look at the Type '{0}' is not usable as an object element page at MSDN.
Also, I believe that classes without any constructors in .NET are automatically provided with 'invisible' parameter-less constructors by default. However, if we add a parameterised constructor, then no parameter-less constructor will be provided automatically.

Related

How to specify generic type argument in XAML

I have a BaseView for my MVP - PRISM WPF application. Now for some reason we thought to make the _presenter as a Templated field in the BaseView.
earlier i had the view xaml representation as
<base:BaseView xamlns:base="clr address of the dll which had BaseView" >
</base:BaseView>
now since i have changed the BaseView to BaseView<TPresenter>, So how shall i write the Xaml then?
You can do it since .NET 4 Framework and XAML 2009.
See Generics in XAML on MSDN
For instance:
<my:BusinessObject x:TypeArguments="x:String,x:Int32"/>
For .NET 3.5:
For XAML 2006 usage when specifically targeting WPF, x:Class must also
be provided on the same element as x:TypeArguments, and that element
must be the root element in a XAML document. The root element must map
to a generic type with at least one type argument. An example is
PageFunction.
Possible workarounds to support generic usages include defining a
custom markup extension that can return generic types, or providing a
wrapping class definition that derives from a generic type but
flattens the generic constraint in its own class definition.
In case this happens to someone. I had a similar scenario where I converted my base class to a templated class (i.e. BaseView to BaseView). I kept receiving errors in the InitializeComponent() method. I was receiving the null exception error in the x:Class base type's InitializeComponent() call. I was able to resolve the errors by removing the form-level events from the XAML definition. If I had to keep the form-level events I would need to move them to BaseView.

What is a ViewModelLocator and what are its pros/cons compared to DataTemplates?

Can someone give me a quick summary of what a ViewModelLocator is, how it works, and what the pros/cons are for using it compared to DataTemplates?
I have tried finding info on Google but there seems to be many different implementations of it and no striaght list as to what it is and the pros/cons of using it.
Intro
In MVVM the usual practice is to have the Views find their ViewModels by resolving them from a dependency injection (DI) container. This happens automatically when the container is asked to provide (resolve) an instance of the View class. The container injects the ViewModel into the View by calling a constructor of the View which accepts a ViewModel parameter; this scheme is called inversion of control (IoC).
Benefits of DI
The main benefit here is that the container can be configured at run time with instructions on how to resolve the types that we request from it. This allows for greater testability by instructing it to resolve the types (Views and ViewModels) we use when our application actually runs, but instructing it differently when running the unit tests for the application. In the latter case the application will not even have a UI (it's not running; just the tests are) so the container will resolve mocks in place of the "normal" types used when the application runs.
Problems stemming from DI
So far we have seen that the DI approach allows easy testability for the application by adding an abstraction layer over the creation of application components. There is one problem with this approach: it doesn't play well with visual designers such as Microsoft Expression Blend.
The problem is that in both normal application runs and unit test runs, someone has to set up the container with instructions on what types to resolve; additionally, someone has to ask the container to resolve the Views so that the ViewModels can be injected into them.
However, in design time there is no code of ours running. The designer attempts to use reflection to create instances of our Views, which means that:
If the View constructor requires a ViewModel instance the designer won't be able to instantiate the View at all -- it will error out in some controlled manner
If the View has a parameterless constructor the View will be instantiated, but its DataContext will be null so we 'll get an "empty" view in the designer -- which is not very useful
Enter ViewModelLocator
The ViewModelLocator is an additional abstraction used like this:
The View itself instantiates a ViewModelLocator as part of its resources and databinds its DataContext to the ViewModel property of the locator
The locator somehow detects if we are in design mode
If not in design mode, the locator returns a ViewModel that it resolves from the DI container, as explained above
If in design mode, the locator returns a fixed "dummy" ViewModel using its own logic (remember: there is no container in design time!); this ViewModel typically comes prepopulated with dummy data
Of course this means that the View must have a parameterless constructor to begin with (otherwise the designer won't be able to instantiate it).
Summary
ViewModelLocator is an idiom that lets you keep the benefits of DI in your MVVM application while also allowing your code to play well with visual designers. This is sometimes called the "blendability" of your application (referring to Expression Blend).
After digesting the above, see a practical example here.
Finally, using data templates is not an alternative to using ViewModelLocator, but an alternative to using explicit View/ViewModel pairs for parts of your UI. Often you may find that there's no need to define a View for a ViewModel because you can use a data template instead.
An example implementation of #Jon's answer
I have a view model locator class. Each property is going to be an instance of the view model that I'm going to allocate on my view. I can check if the code is running in design mode or not using DesignerProperties.GetIsInDesignMode. This allows me to use a mock model during designing time and the real object when I'm running the application.
public class ViewModelLocator
{
private DependencyObject dummy = new DependencyObject();
public IMainViewModel MainViewModel
{
get
{
if (IsInDesignMode())
{
return new MockMainViewModel();
}
return MyIoC.Container.GetExportedValue<IMainViewModel>();
}
}
// returns true if editing .xaml file in VS for example
private bool IsInDesignMode()
{
return DesignerProperties.GetIsInDesignMode(dummy);
}
}
And to use it I can add my locator to App.xaml resources:
xmlns:core="clr-namespace:MyViewModelLocatorNamespace"
<Application.Resources>
<core:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
And then to wire up your view (ex: MainView.xaml) to your viewmodel:
<Window ...
DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}">
I don't understand why the other answers of this question wrap around the Designer.
The purpose of the View Model Locator is to allow your View to instantiate this (yes, View Model Locator = View First):
public void MyWindowViewModel(IService someService)
{
}
instead of just this:
public void MyWindowViewModel()
{
}
by declaring this:
DataContext="{Binding MainWindowModel, Source={StaticResource ViewModelLocator}}"
Where ViewModelLocator is class, which references a IoC and that's how it solves the MainWindowModel property it exposes.
It has nothing to do with providing Mock view models to your view. If you want that, just do
d:DataContext="{d:DesignInstance MockViewModels:MockMainWindowModel, IsDesignTimeCreatable=True}"
The View Model Locator is a wrapper around some (any) Inversion of Control container, such as Unity for example.
Refer to:
How to handle dependency injection in a WPF/MVVM application
http://blog.qmatteoq.com/the-mvvm-pattern-dependency-injection/

Passing large sets of data into user controls

Since UserControls in WPF have to have parameterless constructors, what is the correct way for supplying them with fairly complex data that is needed "near" the time of construction. I have tried using dependency properties for this, but am running into issues with the Visual Studio designer balking at attempts to pass stuff like a Dictionary<string,MyObject> into an IDictionary<string,MyObject> typed dependency property. At some point it must want an exact compile time type match, or the XAML doesn't come up in the designer, although the application executes just fine.
Basically, I want a good way to pass in stuff that I would normally pass into a constructor into a User Control. What's the best way?
Update:
The user control in question will always be created from XAML, so having a non-parameterless construction in addition to the parameterless one is not an option.
Update 2:
An interesting idea would be to have something accessible from the parameterless constructor that I can get my initialization data from. Something like perhaps asking the question: Which of my already initialized ancestors implements an IMyDataProvider interface? This could be similar to how the relative source to ancestor type bindings work, except done programatically from the user control constructor.
If the only problem you are having is passing in derived types, you can pass in instead a simple concrete container class containing your complex types as properties. For example:
public class InitializationData
{
public IDictionary<TKey, TValue> Dictionary { get; set; }
}
This level of indirection will overcome the limitations of the Visual Studio designer.
A couple of options.
1, You can have more than one constructor, a parameterless one for when your control is created via XAML and another that takes a set of parameters for when you create it directly via code. If you definitely don't want to create your instance via code then...
2, Add a public property that only has a setter and is defined with the exact dictionary type you want to pass in and use as the data for initializing the control. The property only needs to be called once. You can have other properties that are getters/setters that expose that initialized data in order more generic types.

What are the main drawbacks of exposing a DependencyProperty via a static property instead of a static field? (F#)

I found out that F# 2.0 apparently doesn't support public static fields anymore, which makes impossible the standard way of implementing a DependencyProperty:
public static readonly FooProperty = DependencyProperty.Register(...); // in C#
I don't quite like one suggested work-around for F# which involves declaring the DependencyProperty as a static mutable val and then initializing it with a static do... (or however exactly it goes).
I've tried exposing a DependencyProperty as a public static property instead of as a public static field, which seems to work just fine in a WPF application (I've tried data binding and style setters on the property, both with success):
type XY() =
inherit Control()
static let fooProperty =
DependencyProperty.Register("Foo", typeof<string>, typeof<XY>)
static member public FooProperty with get () = fooProperty // see update below:
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // not required!
member public this.Foo with get (): string = this.GetValue(fooProperty) :?> string
and set (x: string) = this.SetValue(fooProperty, x)
Are there any notable drawbacks to publishing a dependency property as a property, instead of as a field? Because this code looks much cleaner to me than the suggested work-around.
Update #1: I just found that in the above code, FooProperty (the public read-only property) isn't even required. So one could drop the line I high-lighted in the above code example and things still work just fine. I'm now even more curious why people go to such lengths using mutable val etc. when it's apparently that simple? Am I missing something important?
Update #2: In a comment below, Robert Jeppesen provided a hyperlink to an MSDN page which mentions the following:
If you fail to follow this naming pattern [ie. Foo → FooProperty] , designers might not report your property correctly, and certain aspects of property system style application might not behave as expected.
I put Expression Blend 4 to the test and found that it doesn't seem to be affected at all when the public static FooProperty is completely missing.
Yes, it does make a difference whether you use a public static field or not. But maybe not a significant difference, depending on your needs. I will explain where WPF itself behaves differently, then mention a couple of other situations in which it might also be a problem.
Effect on XAML parsing if you use a static property instead of a static field
The only part of WPF itself that actually notices whether you used a static property or a static field is the XAML parser, and the only situation where it makes a difference is when the same property name is used at multiple levels. This is because the existence of a static field with matching name and ending in "Property" is used to disambiguate between identically-named DependencyProperties at multiple levels.
One place you'll see a difference is if you define your property using a public static property (or nothing at all) and the ancestor class has a DependencyProperty the same name using a public static field, the ancestor class's property will be used instead of yours.
For example, suppose create a Control that has a DependencyProperty named "Language". FrameworkElement already has a "Language" DependencyProperty, but as long as you follow the standard and use a public static field, that's ok: Your "Language" property will take precedence. But if you use a public static property instead, your XAML will end up setting the "FrameworkElement.Language" dependency property, not yours.
This could be a problem if, for example, a new version of WPF comes out that has a new dependency property defined on one of your base classes. For example, if you are using a "Depth" property you've defined using a static field, and NET Framework 5.0 defines a "Depth" property on "Visual", your application won't work on the new version of NET Framework.
Another scenario where this may make a difference is when the class hierarchy is changed. WPF tries to protect you from versioning issues in this case, but its protection goes away if you used a public static property instead of a public static field. The simplest scenario is that you wrote a library and people are using your property. If you used a public static field their compiled application will actually include your class name so there can be no mistake. But if you used a public static property (or nothing at all) their compiled application will reference it using their derived class name. So if the inheritance hierarchy changes or a new property is introduced in between, it could shadow your original property even in compiled code. For example, this could be an issue if:
YourControl is derived from ThirdPartyGrid
YourControl was written when ThirdPartyGrid didn't have a "Language" field, so the compiled code references FrameworkElement.Language
If the vendor of ThirdPartyGrid adds a "Language" dependency property it won't affect your application
But if FrameworkElement.Language had been defined as a public static property, the vendor's addition would break your application
There are some even more esoteric situations where it can make a difference.
Effects on designer tools
As far as I can tell, neither Visual Studio nor Expression Blend behave any differently if you define the property using a public static property instead of a field, or even if you leave it out entirely, except when they encounter the XAML parser behavior mentioned earlier.
But it should be noted that there are many XAML development environments out there, and since the pattern of using static fields is so firmly established, they may rely on this. So it is caveat emptor.
Effects on WPF itself other than XAML parsing
Except for the XAML parser, no part of WPF cares whether you have defined a public static property, field, or nothing at all. You can use your DependencyProperties exactly the same way in each case. However:
I know of no guarantee this will always be true, and
Third party code could easily rely on it

WPF Application base class?

I'm not even sure if this is even possible, but I've just started WPF development on a few new projects and tried to wrap up some common functionality by creating a mini-framework. Just things like exception handling and thread management.
What I would like to do is replace this line...
public partial class App : Application
with
public partial class App : MyFrameworkApplication
I've got the libraries set up and referenced, but I get an error regarding the 'partially' declared App class, presumably because it's still referencing the old base class.
Any ideas? Thanks.
EDIT: #Jeff M: No, your solution didn't work. I suspect because the MyFrameworkApplication is actually in a library and the z namespace declaration fails to recognise the library's namespace. I've got it referenced in the App.xaml.cs, but the suspicious looking error is:
Error 3 Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'MyLibraryNamespace' that is not included in the assembly.
I can circumvent the problem by creating a proxy class within the local namespace and having it derive from the library class...but it's a bit smelly.
I suspect it's because the the underlying XAML root is still an Application as opposed to MyFrameworkApplication. I'd guess the generated baml uses the root as it's parent class. Try changing it to the appropriate names.
e.g.,
<z:MyFrameworkApplication x:Class="MyNamespace.App"
...
xmlns:z="clr-namespace:MyNamespace">
...
</z:MyFrameworkApplication>
It seems my suspicions were correct.
From the docs in Code-Behind and XAML in WPF:
Code-behind, Event Handler, and Partial Class Requirements in WPF
The partial class must derive from the type that backs the root element. (emphasis mine)
Note that under the default behavior of the markup compile build actions, you can leave the derivation blank in the partial class
definition on the code-behind side. The compiled result will assume
the page root's backing type to be the basis for the partial class,
even if it not specified. However, relying on this behavior is not a
best practice.
The event handlers you write in the code behind must be instance methods and cannot be static methods. These methods must be defined by
the partial class within the CLR namespace identified by x:Class. You
cannot qualify the name of an event handler to instruct a XAML
processor to look for an event handler for event wiring in a different
class scope.
The handler must match the delegate for the appropriate event in the backing type system.
For the Microsoft Visual Basic language specifically, you can use the language-specific Handles keyword to associate handlers with
instances and events in the handler declaration, instead of attaching
handlers with attributes in XAML. However, this technique does have
some limitations because the Handles keyword cannot support all of the
specific features of the WPF event system, such as certain routed
event scenarios or attached events. For details, see Visual Basic and WPF Event Handling.
The root application type in code-behind and in the xaml must agree.

Resources