ViewModel constructor containing arguments ins WPF - wpf

How can we bind a user-control to a view-model object, when this last contains parameters in his constructor ???
Does the binding using "DataContext" in the view ensure that when we create a view-model, the view is automatically created ??

If you are using an IoC container, this is supported out-of-the-box.
It really depends on the IoC container you are using, but here is an example using Prism Unity container.
The following examples are taken out from the Prism QuickStarts guide
So, at first, we will have to set up the unity container:
public class QuickStartBootstrapper : UnityBootstrapper
{
private readonly CallbackLogger callbackLogger = new CallbackLogger();
/// <summary>
/// Configures the <see cref="IUnityContainer"/>.
///May be overwritten in a derived class to add specific
/// type mappings required by the application.
/// </summary>
protected override void ConfigureContainer()
{
// Here you can do custom registeration of specific types and instances
// For example
this.Container.RegisterInstance<CallbackLogger>(this.callbackLogger);
base.ConfigureContainer();
}
}
Baisically, youre done!
All you have to do now is have your view recieve the viewModel as a parameter in his constructor, like this:
public partial class OverviewView
{
public OverviewView(OverviewViewModel viewModel)
{
InitializeComponent();
this.DataContext = viewModel;
}
}
Unity IoC container will take care of your parameters in the ViewModel even without you having to register those types most of the times.
Please note that in my answer I only refered to the IoC part of the configuration. setting up an entire MVVM application requires a bit more work and varies depending the MVVM framework you are using

Related

Where to place and configure IoC container in a WPF application?

I am working on a middle sized WPF application (MVVM) that should be extensible and maintainable in the future. Thus I decided to use an IoC container (Unity in this case) to keep things flexible.
However I am not sure where to place and configure Unity in a WPF application.
I guess container should be accessible globally so it should probably go to Application class. But should I make it as static property? Should I configure it in Application_Startup() event handler?
Eg:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static UnityContainer MyUnityContainer;
private void Application_Startup(object sender, StartupEventArgs e)
{
// instantiate and configure Unity
}
}
This way I will be able to access container from any place in the application via static property:
App.MyUnityContainer
I guess this is one way to do it but I am not sure if there are better practices for this issue, specifically for WPF apps.
Have a look at the Composition Root Pattern. What you want to do is to initialize it in your Startup event handler and forget about its existence for the rest of the application.
You are trying to implement the Service Locator Pattern, which according to many is an inferior solution to this problem.
Let me post what I've concluded and hopefully it'll help people out. Correct if there's anything wrong! :P
I guess we'd be looking into something like this:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
UnityContainer myUnityContainer = new UnityContainer();
//make sure your container is configured
myUnityContainer.RegisterType<ISomeDependency, SomeDependencyImplementation>();
myUnityContainer.RegisterType<IMainWindow, MainWindow>();
myUnityContainer.Resolve<IMainWindow>().Show();
}
}
public partial class MainWindow : Window, IMainWindow
{
private ISomeDependency _someDependency;
public MainWindow(ISomeDependency someDependency)
{
_someDependency = someDependency;
}
}
Note there are no globals or singletons, the container survives as long as MainWindow does and all dependencies behind this point of entry further into the composition graph are automagically resolved as long as the container knows about them.
As per new version of Unity container, we have to register it's own instance as well to get it in view models via constructor injection.
App.xaml.cs file:
protected override void OnStartup(StartupEventArgs e)
{
var unityIoC = new UnityContainer();
unityIoC.RegisterTypes(AllClasses.FromAssembliesInBasePath(), WithMappings.FromMatchingInterface, WithName.Default);
unityIoC.RegisterInstance(typeof(IUnityContainer), unityIoC);
}
View Model class
[InjectionConstructor]
public MyViewModel(IUnityContainer container)
{
}
Now unity container would be available for us in view model and can be used to resolve.

Rendering User Control with Abstract Base class in Design Time

I'm working on a project that has several WPF User Controls that inherit from an abstract base class (itself based on UserControl). These controls render just fine at runtime, but they don't render in the designer.
I gather that this happens because the designer attempts to create an instance of the xaml root element, in this case my base class, but it can't create an instance because it is abstract.
For the record, I know that there are "patterns & practices" type issues with having this type of control hierarchy in WPF, but refactoring the entire project is not an option currently.
My question is this: I know that there are design time attributes for setting the DataContext, DesignWidth, etc. What I'm wondering is, can you give a "design time" instance or type to be provided as a replacement when the control is loaded in the designer?
in design time Visual Studio will try to create new Instant of YourUserControl
with parameterless constructor.
if you can't create usercontrol instant like this
var myView = new MyUserControl(); //no params
the designer will fail to render.
if YourUserControl required any parameter. the most popular trick is to create dedicate constructor like this
public MyUserControl() :
this(new MockViewModel(), new MockDataContext){ } // mock Designtime constructor
puclic MyUserControl(IViewModel vm, IDataContext context) //runtime constructor
{
}
in MVVM pattern some UserControl.DataContext is user-defined Type that required some params
XAML
<UserControl.DataContext>
<local:MyViewModel />
</UserControl.DataContext>
You must define parameterless constructor for design-time environment.
public MyViewModel() : this(new MockEventAggregator()) //for designtime
{ }
[ImportingConstructor]
public MyViewModel(IEventAggregator eventAggregator) //for runtime
{
this._eventAggregator = eventAggregator;
//...
}

Silverlight ViewModelLocator defined in app.xaml needs a reference to the DI container

I have a ViewModelLocator class that I am defining in app.xaml which is used by my views to databind to the correct ViewModel.
DataContext="{Binding HomeViewModel, Source={StaticResource Locator}}"
I am using Prism and Unity and my ViewModelLocator class needs a reference to an application level unity container.
I wanted inject the IUnityContainer into the ctor of the ViewModelLocator but the ViewModelLocator gets instanciated from app.xaml using a parameterless ctor.
Is there a preferred way to get access to an application level container - for all other classes in the app I just use ctor injection to get the global container.
What I am currenlty doing for the ViewModelLocator is defining a static variable in my BootStrapper class to store the container. I create the container by overriding the CreateContainer method on UnityBootStrapper.
protected override IUnityContainer CreateContainer()
{
BootStrapper.DIContainer = base.CreateContainer();
return BootStrapper.DIContainer;
}
Then in the ViewModelLocator class I just reference the BootStrapper.DIContainer property to register my viewmodels
BootStrapper.DIContainer.RegisterType<IShellViewModel, DesignShellViewModel>();
This works fine but it is the only place in the application that needs to reference this static property on the bootstrapper - and would like to get rid of it if possible.
thanks
Michael
I had the same issue while converting a Silverlight RIA Business app of mine to use Prism, Unity, and MVVM light toolkit. I came up with this workaround which is to just let the App.xaml create an instance of my ViewModelLocator class and during the application startup event I remove that instance it created from the application resources and re-add an instance using Unity container's Resolve method.
Register the VML with Unity.
Boostrapper.cs: (UnityBootstrapper class)
protected override void ConfigureContainer()
{
Container.RegisterType<ViewModelLocator>(new ContainerControlledLifetimeManager());
base.ConfigureContainer();
}
Use either constructor or property injection in the VML for IUnityContainer. Here I'm using property injection. Also note that the default parameterless constructor is required because App.xaml is going to instantiate its own instance that we'll just wind up throwing away.
ViewModelLocator.cs: (used for blendability)
public class ViewModelLocator
{
[Dependency]
public IUnityContainer Container { get; set; }
public ViewModelLocator() { }
....
}
Remove and re-add the VML to the application resources. Replace the string literal "Locator" with whatever you called your VML in the App.xaml ResourceDictionary section.
App.xaml.cs:
private void Application_Startup(object sender, StartupEventArgs e)
{
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
Resources.Remove("Locator");
Resources.Add("Locator", bootstrapper.Container.Resolve<ViewModelLocator>());
}
Your now cocked, locked, and ready to rock..
I thought I'd follow-up on this since it hasn't been marked as answered.
I've followed a similar approach to Degree451 except I don't remove and re-add the locator as that smells a bit. Instead, I use the built-in capabilities of both Silverlight as well as Unity to handle the problem.
Having the Container property in the ViewModelLocator class marked with the DependencyAttribute means that the class can have its dependencies resolved after instantiation. So in my Bootstrapper, I override ConfigureContainer and add the following code:
var vml = Application.Current.Resources["ViewModelLocator"] as ViewModelLocator;
Container.BuildUp(typeof(ViewModelLocator), vml);
The first line retrieves the instance automatically created by the application from the App.xaml markup. The second line uses Unity to resolve any properties marked with the DependencyAttribute.
To me, this is a much cleaner solution. Of course, it's not Blendable.

What goes in the Main method for WPF / MVVM?

Doing my first MVVM WPF application. I expected to see a Main() method in the App.xaml (I'm used to Silverlight) but it isn't there. I added my own Main method. In Silverlight I then created a View linked to a ViewModel and set it as the RootVisual. How do I correctly open my first View Window in WPF?
There are many ways, but I think the WPF equivalent of setting a Silverlight RootVisual is to call Application.Run
App.Run(new MainWindow())
In general, there is no right or wrong way here nor is there an accepted convention. Some people make this call in the Startup event. Other people don't use the event and override OnStartup instead. Still others use StartupUri in App.xaml.
When I created my first (and to date, only) WPF project, to display the appliation's main window (called MainWindow), I overrode the App class's OnStartup method as below:
/// <summary>
/// Raises the System.Windows.Application.Startup event.
/// </summary>
/// <param name="e">The <see cref="System.Windows.StartupEventArgs" /> that contains the event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// I did some app-specific stuff here...
MainWindow view = new MainWindow();
// Allow all controls in the window to bind to the ViewModel by setting the
// DataContext, which propagates down the element tree.
MainWindowViewModel viewModel = new MainWindowViewModel();
// and I did some more app-specific stuff here...
view.DataContext = viewModel;
view.Show();
}
I believe this was the recommended way for MVVM applications (was a while back though); this code was taken from a .NET 3.5 application.

Dependency Property In WPF/SilverLight

I have searched on google about how to get started with the dependency property used in WPF/silverlight but didn't get any idea of the dependency property, can any one tell me about it , from beginner point of view, so that I get some idea about it and use it in my project
thanks in advance.
Can any one give me link or code example of simple application which explain in simple manner what is dependency Property is ???
I will be very thankfull
I find that implementing a DependencyProperty often involves four parts:
The DependencyProperty itself
Property with get and set
Static changed handler
Instance change handler
You can add a dependency property to a UserControl so that you can data bind to something in the DataContext where the UserControl is instantiated. For example you could add a property to a SoUserControl:
#region SampleProperty // Demo for SO 2424526
public static readonly DependencyProperty SamplePropertyProperty
= DependencyProperty.Register("SampleProperty", typeof(int), typeof(SoUserControl), new PropertyMetadata(OnSamplePropertyChanged));
/// <summary>
/// Demo for SO 2424526
/// Gets or sets dependency property.
/// </summary>
public int SampleProperty
{
get { return (int)GetValue(SamplePropertyProperty); }
set { SetValue(SamplePropertyProperty, value); }
}
/// <summary>
/// Handld changes to SamplePropertyProperty by calling a handler in the associated object.
/// </summary>
/// <param name="obj">object the property is associated with</param>
/// <param name="e">details of change</param>
static void OnSamplePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as SoUserControl).OnSamplePropertyChanged(e);
}
/// <summary>
/// Handle changes to the SamplePropertyProperty dependency property.
/// </summary>
/// <param name="e">details of change</param>
private void OnSamplePropertyChanged(DependencyPropertyChangedEventArgs e)
{
int SamplePropertyNewValue = (int)e.NewValue;
// do something with the internal logic of the control
}
#endregion
From my use with Dependency Properties. They become most important when binding. When you bind to display a regular property, the initial binding will work great, however, the UI will not always update when the property changes, in which case you could implement INotifyPropertyChanged on your class and raise a the NotifyPropertyChanged event, but a Dependency Property will update for you without implementing INotifyProperty Changed.
Triggers is another big one. If you wish to create a Trigger to fire off a WPF Animation whenever one of your properties is set to a certain value... then you need to be triggering off of a dependency property.
DepenedencyProperties can only be implemented on types that derive from DependencyObject.
UIElement derives from Visual which derives from DependencyObject, so most properties from .Net controls are dependency properties already. And when creating and registering my own DependencyProperties it's usually on my custom UserControls as that inherits from UIElement.
It was very frustrating for me when I first tried to create a dependency property on one of my regular classes (you're better off using INotifyPropertyChanged here)
Links:
http://msdn.microsoft.com/en-us/library/ms752914.aspx, http://www.wpftutorial.net/DependencyProperties.html
Have a look at Luis Abreu's blog :http://msmvps.com/blogs/luisabreu/
He's got a lot of info there about dependecy properties and how to use them.
I think you can compare it to the keyword yield.
it allows you to generate a lazy list, or an infinite generator.
every time it's needed one item is requested from that list, and the code continue with the flow.
A dependency property is the same idea for values or content. it computes the needed value, lazily, based on the other values it depends on.
it can cache the value, and when the underlying parts are "dirty", that is, something changed, it will propagate -- invalidate -- all the levels that depend on it.
the object needs to have the facilities of DependencyObject to participate (that is, so the engine will know about it, to introduce it to the chain.)
the mechanism is generic and unfixed, there isn't just one interface to comply with.
but it's somewhat more complex than what I said.
I have found a good explanation, to wire my understanding, in the following blog post:
http://blog.hackedbrain.com/2004/12/04/understanding-dependencyobject-and-dependencyproperty/
You should read a book, for starters.
I have read WPF In Action With Visual Sutdio 2005 from Manning.
As an answer for the negative punctuation just given to me, Dependency Property is part of a bigger plan called WPF and one can't understand Dependency Properties without the basics.
Therefore i think it's a waste of time to try to understand only what is a Dependency Property because i fear one will end up using it incorrectly.
Also, MSDN website has free information about WPF and Dependency Property.

Resources