Hi @all!
Thank you for the great comments regarding the MVVM series! I have moved my blog to a new place on Windows Azure:
New Blog Address
You can expect the last part of the MVVM series this Sunday!
See you there!
awsomedevsigner
Writing about the exciting world of .NET!
Friday, September 6, 2013
Friday, May 10, 2013
AzureDBReverser - Document your Azure SQL Database (Early stage)
This is an early stage demonstration of my AzureDBReverser tool, that you can use later (once it is finished) to document your Azure SQL databases. It is currently only a POC. I have used the Telerik RadDiagram-control for WPF to implement it.
A HD version of the video is available on AzureDBReverser on YouTube.
A HD version of the video is available on AzureDBReverser on YouTube.
Wednesday, May 8, 2013
Windows Store Apps Succinctly – by John Garland (e-book review)
DOWNLOAD LINK
After a short introduction about the core concepts of Windows Store Apps, you will learn the basics about XAML controls and pages.
The book shows you how to work with one of the most important parts in Windows Store development, which is the LayoutAwarePage class. You learn how to adapt your application to the different view states supported by Windows 8, such as full screen, snapped, and filled, and how to adapt your layout to make your apps look good on any screen, in any orientation.
Like Windows Phone, navigation is an essential part of every application and a serious part of the usability concept. You will learn how to invoke navigation and how to use events like Navigating and Navigated, and how to implement the different methods (OnNavigatingFrom, OnNavigatedFrom) to make your app shine.
Users want to share content with friends, colleagues, and their families. Windows 8 supports content sharing via the Charms bar. The author shows you how to use the Share Contract in your app and how to share content between your app and other apps. This includes text, images, file references, and more. Communication with devices, such as using the Print Contract to print, concludes the Charms chapter.
To make your application stand out in contrast with other apps and to give your user an additional source of information, Windows 8 offers you the possibility to present important updates using tiles, secondary tiles, and badges. You will learn how to update your tiles, send toast and push notifications, and how to add and remove secondary tiles.
Every modern tablet or laptop today offers a wide range of sensors and devices, like an accelerometer, a compass, or a light sensor. Garland describes how to utilize those devices in your applications and add additional value to your applications. Accessing and interacting with multimedia devices like cameras and microphones gives the Hardware and Sensors chapter the perfect happy ending.
The last chapter covers the Windows Store. It explains Windows Store basics like application submission, pricing, registering, and submitting applications. Monetization instruments like application trail modes, in-app-purchases, and ads for your apps are explained in depth, as well as other ways to distribute your applications.
Conclusion
John Garland is a senior consultant at Wintellect and has been developing software professionally since the 1990s.The book reflects John’s development experience and in-depth knowledge of the Windows 8 platform, and can be fully recommended to every developer who wants to dive into Windows Store application development.
Monday, April 8, 2013
Windows Azure Recovery Services - Now Available!
You can schedule backups for Windows Server 2012, System Center 2012 SP1 - Data Protection Manager, and Windows Server 2012 Essentials.
To subscribe to the Azure Recovery Services you need to register for the preview. Just select => NEW=>DATA SERVICES => RECOVERY SERVICES and register for the preview. I have tested the Recovery Services with a fresh install of Server 2012 Standard Edition, running in Hyper-V.
A Backup Test
Create a new backup vault (that's where your data will be stored) and proceed:After some time Azure will return, and indicate, that your backup vault was successfully created. You will get a notice, to install a certificate to your backup vault. I have done this immediately, but best is, to install it, when you download the backup agent. This certificate needs to be generated on the Sever and uploaded to the vault certificate store. If you generate the certificate on another machine, the upload will be denied.
Now download the backup agent and install it:
After you installed the Backup-Agent, run mmc => Windows Key + R, type "mmc" (this runs the server management console), and add the Windows Azure Backup Snap-In: Choose File=>Add/Remove Snap-in...=>Windows Azure Backup:
The Windows Azure Backup Snap-In will be installed now:
Add you proxy configuration settings:
Choose your preferred technique to setup a self-signed X509 Version 3 certificate. I prefer using makecert.exe. If you don't have makecert.exe on your machine, you can install the Windows 8 SDK on a Server 2012 (like I did). You can find the Windows 8 SDK binaries and makecert.exe after a successful install in C:\Program Files (x86)\Windows Kits\8.0\bin\X86. If you need to know, how to use makecert.exe to generate your certificate please visit this link: Upload Certificates to the Vault .
Now set your encryption settings. It is recommended (and not like seen in this screenshot), to export the encryption settings to a USB-stick or other external backup media:
After a successful registration, you can visit the Azure Portal, and check your registered server:
Everything is ready now to schedule a backup. Choose "Schedule Backup" from within the "Actions" pane on the right hand side:
Choose the items you want to backup:
Specify the backup time:
Specify the Retention Settings:
To test backup speed etc., choose "Backup Up Now" from the Actions-Pane and click on Back Up. The agent will start to back-up your selected files:
After the backup is finished, you can see your "backup-set" under "Protected Items" in your Recovery Servcies:
Wow! That was really easy. Without any further documentation I was able to setup my backup very quickly within a few minutes, without being a professional systems administrator. Now I can backup my important data to Azure. Well done Azure Team!
Friday, April 5, 2013
Expression Blend Changes - Visual Studio 2012 Update 2 RTM
Performance Improvements
- Opening XAML files in WPF project with a common 3rd party WPF library set improved by 54.4 % (WOW!)
- Drag and drop a WPF control from the toolbox for a 3rd party WPF control library set improved by 80%!
- Openin XAML file from default Windows Store XAML Grid app with a large number of assembly references unused from XAML improved by 86.1 % !
Issues Fixed
- 30% of all issues submitted via Microsoft Connect
Photoshop and Illustrator import for Windows Store Projects
- Import Photoshop and Illustrator files into Windows Store XAML apps now, like in WPF, Silverlight and Windows Phone!
Performance and Reliability
- Performance improvements for Blend and Visual Studio 2012 regarding the XAML design surfaces, especially improvements in XAML load time (some issues fixed, work still in progress)
WPF, and SketchFlow are Back!
Create WPF, Silverlight and SketchFlow projects like before in Expression Blend 4:
And here the new Tools=>Options=>SketchFlow settings:
Read more details and catch the latest updates on blendinsider !
Sunday, March 3, 2013
Are you ready to become the Ip Man ? - You better be prepared!
Courtesy of Mandarin Films (Original title "ye wen 2")
This is the second blog post I am writing about starting a new business. The inspiration to write this post came up during my relaxation session, after learning some additional in-depth XAML techniques watching the legendary movie “Ip Man2”. In case you have not seen the movie, you should watch it, before reading this post. That’s my personal advice.
Preparing yourself to enter the scene
Before entering the scene learn your business well. Learn everything you can that you are passionate about and what makes you feel proud. Practice every day using your knowledge for something meaningful, that will take you to the next level. This is what a real master does. If you are serious about what you do, practicing will become an inherent part of your everyday life.Hitting the ground – meeting your competitors
Ignorance will fill the space between you and your competitors as long as your ability to make money and attract customers is not becoming public, or your business-idea is starting to attract interest. This is the point of no return, or the last milestone in your project. Now, they know who you are. They feel that you are willing to claim a piece of the cake. And they will do anything to prevent you from sitting down at “their” table enjoying your meal.Ready for the face-off
Now that you have hit the ground, you have to show, that you are a real master in your area, and that you are willing to fight to grow your business and to become a local player. “Local” however needs to be re-defined here. The world is getting small. It’s a global business, but you can spread your message about what you do and what you offer within seconds around the globe!Some of them will accept you as an equal partner right away after the first confrontation. But some of them will try to put your credibility down, or they will try to let your starve out, by blocking needed resources like freezing your credits or trying to sell your idea behind your back to third parties, you don’t even know about. This is what they think, but as a real master, you are prepared.
One key to be prepared for situations like that, is a in-depth knowledge of your own social-graph aka your sociogram.
Bring those voices, tweets and e-mails to life by visualizing them, turning them into real people. Analyze the connections they have. Knowing your social-graph, one essential key to your success. Why do you think big companies pay huge amounts of money to use all those big-data analytical tools? Build your own strategies on what you see and what happens in your own social environment. And please, don’t focus only on internet-services.
You can do that on your own, until your small business begins to grow and becomes mature.
You have been accepted – the biggest player of all is asking for a meeting
The leading force has asked you to share some of your precious time, or – like in “Ip Man 2” you asked for a final clarification. You had already the opportunity during the face-off to show what you got, and you went out of the face-off as an equivalent opponent.As a master your are prepared for the finial fight, and you know how to do a clean fight, and you know when its best to stop the fight.
Turning your biggest opponents into partners
Already the ancient “Art of War” tells you, that if you can’t beat your enemy, to turn them into allies.Well, that’s for the case you see that a specific situation could not lead to the expected result. This is something your should know and be prepared for, before you meet your possible future partners.
Check the market and learn about your opponents. Check out what they are best at, and how they do it. Learn about their leaders, their products and strategies. Monitor them by using the shining new tools available on the market today. Many of them are free, like webiste-monitoring and much more.
But remember to do that in a really early stage, before hitting the market with your company and products.
This will automatically create respect between you and the other party, you are competing with. They will see, that you are very well informed about them, and that you are someone serious. An equal opponent, worth working against, or worth partnering with.
Respect
Regardless of all the fights and difficult situations you will pass, never forget to be respectful, reliable and engaging. This are the key ingredients for a successful and from my standpoint “clean” business relationship. What works in real life, works most of the time also in business.Thursday, February 28, 2013
MVVM for Windows Phone Developers–Use it Guys! (Part 3)
In the last part of this series we extended our solution with a PCL library for our models, view-models, and we added a Windows 8 project as well as a testing project for Windows 8.
Preparing our projects to with the right version of MVVM Light
We added a the NuGet package “MVVM LIght libraries only (PCL)”. To install the same binary versions, and the specific platform libraries, we need to add the package to our Windows Phone 8 and our Windows 8 project. The installer will install the base-libraries and the specific libraries for Windows Phone 8 and Windows 8.
TIP: Somehow the portable package is only working, when adding the portable package of “BCL Portability Pack for .NET Framework3, Silverlight 4 and 5, And Windows Phone 7.5”. Just search for “Microsoft BCL” and install the package.
Architecture changes
Through the use of PCL, we have a major change in our architecture. All models, view-models and our DAL-Helpers will be located in our PCL library.
Here is the changed diagram:
You see, that all the parts we need are now located in the PCL library.
Through this architectural change, we need to handle now other problems, that come up with PCL.
We can use a “centralized” view-model-locator, that will help us, to locate our view-models via static-properties, or should we try another approach?
And some other questions that come up like: “How can we manage the data-access in a generic way?”.
Ok. We have certain types that are implemented by our view-models and model classes. We have also interfaces that are implemented by our units-of-work and our repositories.
This is a very good use-case for dependency injection. We roll up everything bottom-up based on our architecture diagram.
Expand our MVVMWindowsPhone.Core.Portable (maybe this should be renamed) and right-click the folder DAL. Select “Add new item…” and add a new interface, name it “IUnitOfWork”. Add the following code:
This interface has one property of type T called “Context” this will hold our “Database access object” like a context used for EF or the SQLiteConnection object, to perform actions to our databases. Every platform like Windows 8 or Windows Phone 8 will have it’s own implementation.
The next interface to add is the “IRepository” interface, it will be placed into the DAL folder also:
This interface has the following members:
Ninject is also available for portable class libraries. So right-click the “References” entry in our portable-core project and choose “Manage NuGet-Packages…”. Type “ninject-portable” into the search-box on the right side and install the entry stating “Ninject for Portable Class Libraries”. That’s it.
To understand Ninject, and how it basically works, you can visit the Ninject Wiki here:
Ninject-Wiki
However, if you want to learn more about dependency injection using .NET you can buy this book:
Dependency injection in .NET (I don’t know the author, and I am not making any money with that. I love the book)
The base requirements for the bootstrapper are:
We have installed Ninject now, and we have set the base requirements for our bootstrapper.
Now we need to add the base interfaces and classes we will need later in our implementation, these include:
A base view-model, that we can use to inject the required parts we need, like the repository and the unit-of-work
With service interfaces are meant here. This interfaces offer “services” like navigation and settings management. This can be confusing, because the most people think about web-services or similar things when hearing that.
To have everything in place, create a new project-folder inside our portable core project and add two new interfaces:
Here is the code for the two files:
We have an overload of the NavigateTo-Method here. The first one is for Windows Phone and the second one is for Windows 8. The GoBack-Method is for both systems. For the sake of simplicity I am not breaking this down into a partial interface or two single interfaces.
This “Service” has three members, where two of it are generic. We will later use those generic methods to serialize complete types on each platform with serialization frameworks.
We are using MVVM-Light here (the portable branch), this means that we want to get all the advantages of MVVM-Light we want to use. The basic view-model class in MVVM-Light is called “ViewModelBase”. This class offers us the following things out of the box:
Here is the original ViewModelBase class from the MVVM-Light (the portable version) just to give you a feeling about what it offers (Courtesy of MVVM-Light):
We inherit from the “ViewModelBase” class and add two generic type parameters T,U. Where T stands for the type of our current model-class we want to use and U stands for the current unit-of-work we want to use. The injection-technique we use here is constructor-injection. You can see the “[Injection]” attribute placed on the constructor of our “BaseViewModel”.
We have the following members in our BaseViewModel:
The VML (View-Model-Locator) is responsible to deliver the view-models for our view. The current implementation of the VML is quite different from the standard VML of MVVM-Light:
Because of the generic implementation of the BaseViewModel-class, I came up with the indexer of type dynamic. You can see that there is a Dictionary<string,ViewModelBase> defined. Our BaseViewModel-class has two generic type parameters, that can be reference types of any kind. Therefore creating a VML with those type parameters would allow us only to host view-models of a certain type, and that’s not what is the goal here. Therefore the dictionary “ViewModels” contain the base type “ViewModelBase”. The indexer is of type dynamic. Therefore getting a property from our ViewModel will be resolved dynamically at runtime.
And here is the corresponding interface “IViewModelLocator” used later for injection:
Through the basic structure of PCL projects, supporting different platforms, we move to the direction of abstracting as much as possible of our portable core by using interfaces and abstract classes.
The next thing to do, is to install the respective components for Ninject in our Windows 8 and Windows Phone 8 projects. Fire up the NuGet reference dialog and install the portable version of Ninject in both projects. This will add some platform-specific assemblies to each of the platforms. Check the reference folder after installing the assemblies.
This should give you (and hopefully me, too, once and forever) the hint, how all the PCL stuff works:
The current implementation for the basic bootstapper, requires to add two new files to our PCL project:
As always, you can name the files to whatever you prefer. Here is the source:
This interface has the following members:
And here is the abstract class we use later to derive from in our WP8 and Win8 projects:
We will use the ConfigureBootstrapper-Method later, to configure and setup everything we need to work successfully with Ninject.
In the next part, I show you how to put all this stuff together.
Thank you for reading. If you have ideas, or want to see something additional here, let me know. All the code is hosted on GitHub: https://github.com/Injac/WindowsPhone8MVVM
Preparing our projects to with the right version of MVVM Light
We added a the NuGet package “MVVM LIght libraries only (PCL)”. To install the same binary versions, and the specific platform libraries, we need to add the package to our Windows Phone 8 and our Windows 8 project. The installer will install the base-libraries and the specific libraries for Windows Phone 8 and Windows 8.
TIP: Somehow the portable package is only working, when adding the portable package of “BCL Portability Pack for .NET Framework3, Silverlight 4 and 5, And Windows Phone 7.5”. Just search for “Microsoft BCL” and install the package.
Architecture changes
Through the use of PCL, we have a major change in our architecture. All models, view-models and our DAL-Helpers will be located in our PCL library.
Here is the changed diagram:
You see, that all the parts we need are now located in the PCL library.
Through this architectural change, we need to handle now other problems, that come up with PCL.
We can use a “centralized” view-model-locator, that will help us, to locate our view-models via static-properties, or should we try another approach?
And some other questions that come up like: “How can we manage the data-access in a generic way?”.
Solution
Implement a bootstrapper for MVVM-Light with Ninject
Ok. We have certain types that are implemented by our view-models and model classes. We have also interfaces that are implemented by our units-of-work and our repositories.
This is a very good use-case for dependency injection. We roll up everything bottom-up based on our architecture diagram.
Adding the IUnit of work interface
Expand our MVVMWindowsPhone.Core.Portable (maybe this should be renamed) and right-click the folder DAL. Select “Add new item…” and add a new interface, name it “IUnitOfWork”. Add the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace MVVMWindowsPhone.Core.Portable.DAL
{
/// <summary>
/// Unit of work to use as abstraction.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IUnitOfWork<T> where T:class
{
/// <summary>
/// The context to work with
/// the specific database, file,
/// whatever.
/// </summary>
T Context {get; set;}
/// <summary>
/// Set the current context.
/// Since we cannot use constructors
/// in interfaces.
/// </summary>
/// <param name="context"></param>
void SetContext(T context);
}
}
This interface has one property of type T called “Context” this will hold our “Database access object” like a context used for EF or the SQLiteConnection object, to perform actions to our databases. Every platform like Windows 8 or Windows Phone 8 will have it’s own implementation.
The next interface to add is the “IRepository” interface, it will be placed into the DAL folder also:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace MVVMWindowsPhone.Core.Portable.DAL
{
public interface IRepository<T,U> where T:class where U:class
{
/// <summary>
/// The unit of work to use.
/// Like SQLite, or file driver.
/// </summary>
IUnitOfWork<U> Driver {get; set;}
/// <summary>
/// Get all entries.
/// </summary>
/// <returns></returns>
IQueryable<T> GetAllEntries();
/// <summary>
/// Get filtered entries.
/// </summary>
/// <param name="data"></param>
/// <param name="filter"></param>
/// <returns></returns>
IQueryable<T> GetFilteredEntries(IEnumerable<T> data, Expression<Func<T, bool>> filter);
/// <summary>
/// DeleteEntry
/// </summary>
/// <param name="entry"></param>
/// <returns></returns>
T DeleteEntry(T entry);
/// <summary>
/// Update Entry.
/// </summary>
/// <param name="entry"></param>
/// <param name="updateValue"></param>
/// <returns></returns>
T UpdateEntry(T entry, T updateValue);
/// <summary>
/// Add a new entry.
/// </summary>
/// <param name="Entry"></param>
/// <returns></returns>
T AddEntry(T Entry);
}
}
This interface has the following members:
- IUnitOfWork<U> => Our db access object
- IQueyable<T> GetAllEntries() => Get all entries from a specific table, of file
- IQueryable<T> GetFilteredEntries(IEnumeralable<T> data, Expression<Func<T, bool>> filter) => allows us, to filter for specific values using LINQ
- T DeleteEntry(T Entry) => allows us to delete a specific entry
- T UpdateEntry(T Entry, T updateValue) => allows us to update a specific entry. This is not commonly used in an IRepository. If we would use EF (EntityFramework) we could ignore this member. But we are using SQLight, which still seems to have problems with atomic database actions.
- T AddEntry(T Entry) => Add a new entry to a table or file, or whatever we use to save data (like a web-service for example)
Install Ninject for Portable Class Libraries
Ninject is also available for portable class libraries. So right-click the “References” entry in our portable-core project and choose “Manage NuGet-Packages…”. Type “ninject-portable” into the search-box on the right side and install the entry stating “Ninject for Portable Class Libraries”. That’s it.
The bootstrapper based on Ninject
To understand Ninject, and how it basically works, you can visit the Ninject Wiki here:
Ninject-Wiki
However, if you want to learn more about dependency injection using .NET you can buy this book:
Dependency injection in .NET (I don’t know the author, and I am not making any money with that. I love the book)
The base requirements for the bootstrapper are:
- Localize and create instances of the view-models we use
- Inject all the interfaces and load the respective types, tied to those interfaces, or hosting the interfaces
- Create a locator, that enables us to use the view-models in our applications on Windows Phone 8 and Windows 8
Preparing the bootstrapper implementation
We have installed Ninject now, and we have set the base requirements for our bootstrapper.
Now we need to add the base interfaces and classes we will need later in our implementation, these include:
A base view-model, that we can use to inject the required parts we need, like the repository and the unit-of-work
- Basic service for navigation
- Basic service to handle application settings
With service interfaces are meant here. This interfaces offer “services” like navigation and settings management. This can be confusing, because the most people think about web-services or similar things when hearing that.
Adding the services
To have everything in place, create a new project-folder inside our portable core project and add two new interfaces:
- INavigationService
- ISettingsService
Here is the code for the two files:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MVVMWindowsPhone.Core.Portable.Services
{
/// <summary>
/// The navigation service to
/// enable page navigation.
/// For all our platforms.
/// </summary>
public interface INavigationService
{
/// <summary>
/// Navigate to a specific page.
/// Used for Windows phone.
/// </summary>
/// <param name="page">The absolute uri to the page to navigate to.</param>
void NavigateTo(Uri page);
/// <summary>
/// Used for Windows 8.
/// </summary>
/// <param name="pageToNavigateTo"></param>
void NavigateTo(Type pageToNavigateTo);
/// <summary>
/// Go back to
/// the previous page.
/// Used for Windows Phone and Windows 8.
/// </summary>
void GoBack();
}
}
We have an overload of the NavigateTo-Method here. The first one is for Windows Phone and the second one is for Windows 8. The GoBack-Method is for both systems. For the sake of simplicity I am not breaking this down into a partial interface or two single interfaces.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MVVMWindowsPhone.Core.Portable.Services
{
/// <summary>
/// This is our settings
/// servcie. To save and
/// load settgins.
/// </summary>
public interface ISettingsService
{
/// <summary>
/// Save a setting.
/// </summary>
/// <typeparam name="T">The type to save.</typeparam>
/// <param name="value">The value of T to save.</param>
/// <param name="key">The key under which to save the value.</param>
/// <returns></returns>
bool SaveSetting<T>(T value, string key);
/// <summary>
/// Load a setting.
/// </summary>
/// <typeparam name="T">The type to save.</typeparam>
/// <param name="value">The value of T to save.</param>
/// <param name="key">The key under which to save the value.</param>
/// <returns></returns>
T LoadSetting<T>(T value, string key);
/// <summary>
/// Remove a settings entry
/// with a specific key.
/// </summary>
/// <param name="key">The key to pin the settings entry to delete.</param>
/// <returns></returns>
bool RemoveSetting(string key);
}
}
This “Service” has three members, where two of it are generic. We will later use those generic methods to serialize complete types on each platform with serialization frameworks.
The base view-model
We are using MVVM-Light here (the portable branch), this means that we want to get all the advantages of MVVM-Light we want to use. The basic view-model class in MVVM-Light is called “ViewModelBase”. This class offers us the following things out of the box:
- Design-Time mode detection (in the PCL version, for different systems)
- Messaging
- PropertyChanged notification (Inheriting from ObservableObject another MVVM-Class that offers various possibilities to raise a property changed notification)
Here is the original ViewModelBase class from the MVVM-Light (the portable version) just to give you a feeling about what it offers (Courtesy of MVVM-Light):
using GalaSoft.MvvmLight.Helpers;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace GalaSoft.MvvmLight
{
public abstract class ViewModelBase : ObservableObject, ICleanup
{
private static bool? _isInDesignMode;
private IMessenger _messengerInstance;
public bool IsInDesignMode
{
get
{
return ViewModelBase.IsInDesignModeStatic;
}
}
public static bool IsInDesignModeStatic
{
get
{
if (!ViewModelBase._isInDesignMode.HasValue)
{
ViewModelBase._isInDesignMode = new bool?(ViewModelBase.IsInDesignModePortable());
}
return ViewModelBase._isInDesignMode.Value;
}
}
protected IMessenger MessengerInstance
{
get
{
IMessenger messenger = this._messengerInstance;
IMessenger @default = messenger;
if (messenger == null)
{
@default = Messenger.Default;
}
return @default;
}
set
{
this._messengerInstance = value;
}
}
public ViewModelBase() : this(null)
{
}
public ViewModelBase(IMessenger messenger)
{
this.MessengerInstance = messenger;
}
protected virtual void Broadcast<T>(T oldValue, T newValue, string propertyName)
{
PropertyChangedMessage<T> propertyChangedMessage = new PropertyChangedMessage<T>(this, oldValue, newValue, propertyName);
this.MessengerInstance.Send<PropertyChangedMessage<T>>(propertyChangedMessage);
}
public virtual void Cleanup()
{
this.MessengerInstance.Unregister(this);
}
private static bool IsInDesignModeMetro()
{
bool value;
try
{
Type type = Type.GetType("Windows.ApplicationModel.DesignMode, Windows, ContentType=WindowsRuntime");
PropertyInfo property = type.GetProperty("DesignModeEnabled", BindingFlags.Static | BindingFlags.Public);
value = (bool)property.GetValue(null, null);
}
catch
{
value = false;
}
return value;
}
private static bool IsInDesignModeNet()
{
bool flag;
try
{
Type type = Type.GetType("System.ComponentModel.DesignerProperties, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
object value = type.GetField("IsInDesignModeProperty", BindingFlags.Static | BindingFlags.Public).GetValue(null);
Type type1 = Type.GetType("System.ComponentModel.DependencyPropertyDescriptor, WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
Type type2 = Type.GetType("System.Windows.FrameworkElement, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
MethodInfo[] methods = type1.GetMethods(BindingFlags.Static | BindingFlags.Public);
MethodInfo[] methodInfoArray = methods;
MethodInfo methodInfo = ((IEnumerable<MethodInfo>)methodInfoArray).Single<MethodInfo>((MethodInfo mi) => {
if (mi.Name != "FromProperty")
{
return false;
}
else
{
return (int)mi.GetParameters().Length == 2;
}
});
object[] objArray = new object[] { value, type2 };
object obj = methodInfo.Invoke(null, objArray);
PropertyInfo property = type1.GetProperty("Metadata", BindingFlags.Instance | BindingFlags.Public);
object value1 = property.GetValue(obj, null);
Type type3 = Type.GetType("System.Windows.PropertyMetadata, WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
PropertyInfo propertyInfo = type3.GetProperty("DefaultValue", BindingFlags.Instance | BindingFlags.Public);
bool flag1 = (bool)propertyInfo.GetValue(value1, null);
flag = flag1;
}
catch
{
flag = false;
}
return flag;
}
private static bool IsInDesignModePortable()
{
DesignerPlatformLibrary detectedDesignerLibrary = DesignerLibrary.DetectedDesignerLibrary;
if (detectedDesignerLibrary != DesignerPlatformLibrary.WinRT)
{
if (detectedDesignerLibrary != DesignerPlatformLibrary.Silverlight)
{
if (detectedDesignerLibrary != DesignerPlatformLibrary.Net)
{
return false;
}
else
{
return ViewModelBase.IsInDesignModeNet();
}
}
else
{
bool flag = ViewModelBase.IsInDesignModeSilverlight();
if (!flag)
{
flag = ViewModelBase.IsInDesignModeNet();
}
return flag;
}
}
else
{
return ViewModelBase.IsInDesignModeMetro();
}
}
private static bool IsInDesignModeSilverlight()
{
bool value;
try
{
Type type = Type.GetType("System.ComponentModel.DesignerProperties, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e");
PropertyInfo property = type.GetProperty("IsInDesignTool", BindingFlags.Static | BindingFlags.Public);
value = (bool)property.GetValue(null, null);
}
catch
{
value = false;
}
return value;
}
protected virtual void RaisePropertyChanged<T>(string propertyName, T oldValue, T newValue, bool broadcast)
{
if (!string.IsNullOrEmpty(propertyName))
{
this.RaisePropertyChanged(propertyName);
if (broadcast)
{
this.Broadcast<T>(oldValue, newValue, propertyName);
}
return;
}
else
{
throw new ArgumentException("This method cannot be called with an empty string", "propertyName");
}
}
protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression, T oldValue, T newValue, bool broadcast)
{
PropertyChangedEventHandler propertyChangedHandler = base.PropertyChangedHandler;
if (propertyChangedHandler != null || broadcast)
{
string propertyName = base.GetPropertyName<T>(propertyExpression);
if (propertyChangedHandler != null)
{
propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
}
if (broadcast)
{
this.Broadcast<T>(oldValue, newValue, propertyName);
}
}
}
protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue, bool broadcast)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
this.RaisePropertyChanging<T>(propertyExpression);
T t = field;
field = newValue;
this.RaisePropertyChanged<T>(propertyExpression, t, field, broadcast);
return true;
}
else
{
return false;
}
}
protected bool Set<T>(string propertyName, ref T field, T newValue, bool broadcast)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
this.RaisePropertyChanging(propertyName);
T t = field;
field = newValue;
this.RaisePropertyChanged<T>(propertyName, t, field, broadcast);
return true;
}
else
{
return false;
}
}
}
}
Add a new class to the folder “ViewModel” (in our portable core project) we added it in the last part before and name it “BaseViewModel.cs”. We will inherit from “ViewModelBase” and add some additional features we need for our sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GalaSoft.MvvmLight;
using MVVMWindowsPhone.Core.Portable.DAL;
using System.Collections.ObjectModel;
using MVVMWindowsPhone.Core.Portable.Services;
using Ninject;
namespace MVVMWindowsPhone.Core.Portable.ViewModel
{
/// <summary>
/// Our base-view model
/// based on the ViewModelBase
/// of MVVM-Light portable, with
/// two generic type parameters
/// to support our IRepository.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="U"></typeparam>
public class BaseViewModel<T,U>:ViewModelBase where U:class where T:class
{
/// <summary>
/// The data we need for our ViewModel.
/// </summary>
private ObservableCollection<T> data;
/// <summary>
/// Our navigation service we need.
/// </summary>
private readonly INavigationService navigationService;
/// <summary>
/// The data we need for our ViewModel.
/// </summary>
public ObservableCollection<T> Data
{
get { return data; }
set { data = value; }
}
/// <summary>
/// The repository we use.
/// </summary>
private readonly IRepository<T,U> repository;
/// <summary>
/// Our constructor.
/// This one will be used
/// to inject our repository.
/// </summary>
/// <param name="repo"></param>
[Inject]
public BaseViewModel(IRepository<T,U> repo,INavigationService navService)
{
this.repository = repo;
this.navigationService = navService;
this.Model = new ObservableCollection<T>();
}
}
}
We inherit from the “ViewModelBase” class and add two generic type parameters T,U. Where T stands for the type of our current model-class we want to use and U stands for the current unit-of-work we want to use. The injection-technique we use here is constructor-injection. You can see the “[Injection]” attribute placed on the constructor of our “BaseViewModel”.
We have the following members in our BaseViewModel:
- Data => This is our main collection that will contain our entries, based on the type for our model we pass through the generic parameter U
- navigationService => Here we pass an instance of the INavigationService interface. This will be done through constructor injection utilizing Ninject
- repository => this is the IRepository implementation that we will inject into our view-model through constructor injection
The View-Model-Locator
The VML (View-Model-Locator) is responsible to deliver the view-models for our view. The current implementation of the VML is quite different from the standard VML of MVVM-Light:
using GalaSoft.MvvmLight;
using MVVMWindowsPhone.Core.Portable.Bootstrapper;
using MVVMWindowsPhone.Core.Portable.DAL;
using MVVMWindowsPhone.Core.Portable.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
namespace MVVMWindowsPhone.Core.Portable.ViewModel
{
/// <summary>
/// The ViewModel locator.
/// </summary>
public class ViewModelLocator:IViewModelLocator
{
/// <summary>
/// Our view models.
/// </summary>
Dictionary<string, ViewModelBase> viewModels;
/// <summary>
/// Our view models.
/// </summary>
public Dictionary<string, ViewModelBase> ViewModels
{
get { return viewModels; }
set { viewModels = value; }
}
/// <summary>
/// Standard constructor.
/// </summary>
public ViewModelLocator()
{
ViewModels = new Dictionary<string,ViewModelBase>();
}
/// <summary>
/// Set and get your ViewModels
/// here.
/// </summary>
/// <param name="viewModelName">The name of the viewmodel to get or set.</param>
/// <returns>The viewmodel selected.</returns>
public dynamic this[string viewModelName]
{
get
{
if(ViewModels.ContainsKey(viewModelName))
{
return this.ViewModels[viewModelName];
}
else
{
return null;
}
}
}
}
}
Because of the generic implementation of the BaseViewModel-class, I came up with the indexer of type dynamic. You can see that there is a Dictionary<string,ViewModelBase> defined. Our BaseViewModel-class has two generic type parameters, that can be reference types of any kind. Therefore creating a VML with those type parameters would allow us only to host view-models of a certain type, and that’s not what is the goal here. Therefore the dictionary “ViewModels” contain the base type “ViewModelBase”. The indexer is of type dynamic. Therefore getting a property from our ViewModel will be resolved dynamically at runtime.
And here is the corresponding interface “IViewModelLocator” used later for injection:
using System;
using System.Collections.Generic;
using GalaSoft.MvvmLight;
namespace MVVMWindowsPhone.Core.Portable.Bootstrapping
{
/// <summary>
/// The base for our Viewmodel locator.
/// </summary>
interface IViewModelLocator
{
/// <summary>
/// The indexer to get the
/// right ViewModel.
/// </summary>
/// <param name="viewModelName"></param>
/// <returns></returns>
dynamic this[string viewModelName] { get; }
/// <summary>
/// The dictionary to
/// save the ViewModels to.
/// </summary>
Dictionary<string, ViewModelBase> ViewModels { get; set; }
}
}
The bootstrapper
Through the basic structure of PCL projects, supporting different platforms, we move to the direction of abstracting as much as possible of our portable core by using interfaces and abstract classes.
The next thing to do, is to install the respective components for Ninject in our Windows 8 and Windows Phone 8 projects. Fire up the NuGet reference dialog and install the portable version of Ninject in both projects. This will add some platform-specific assemblies to each of the platforms. Check the reference folder after installing the assemblies.
This should give you (and hopefully me, too, once and forever) the hint, how all the PCL stuff works:
- Add a base component like the Ninject portable that can be understood by the chosen platforms configured for the PCL library
- Add the abstractions like interfaces, abstract classes to the PCL library, to be used for every single platform
- Add the specific platform dependencies to your chosen platforms like Win8, WP8, what ever you chose
- Add an entry point (a method) to new-up the needed classes to make that stuff run
The current implementation for the basic bootstapper, requires to add two new files to our PCL project:
- IBootStrapper.cs => The base interface for our bootstrapper
- SimpleBootstrapper.cs (an abstract class to be implemented later in WP8 and Win8)
As always, you can name the files to whatever you prefer. Here is the source:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
using Ninject.Modules;
using MVVMWindowsPhone.Core.Portable.Bootstrapping;
namespace MVVMWindowsPhone.Core.Portable.Bootstrapper
{
/// <summary>
/// Defines the basics for our
/// simple bootstrapper.
/// </summary>
public interface IBootstrapper
{
/// <summary>
/// The Ninject kernel we
/// need to load what needs
/// to be injected.
/// </summary>
IKernel Container {get;set;}
/// <summary>
/// The ViewModel-Locator
/// we need later for data-binding.
/// </summary>
IViewModelLocator ViewModelLocator {get;set;}
/// <summary>
/// The Ninject modules to load.
/// </summary>
IList<INinjectModule> Modules {get;set;}
/// <summary>
/// Configure the "parts"
/// we want to use in
/// our project.
/// </summary>
void ConfigureBootstrapper();
}
}
This interface has the following members:
- Container of type IKernel => the Ninject kernel we will use later
- ViewModelLocator of type IViewModelLocator => We will use this one later to “load” our view-models via Ninject
- Modules of type IList<INinjectModule> => our Ninject modules will be “loaded” into this member
And here is the abstract class we use later to derive from in our WP8 and Win8 projects:
using MVVMWindowsPhone.Core.Portable.Bootstrapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
using Ninject.Modules;
namespace MVVMWindowsPhone.Core.Portable.Bootstrapping
{
/// <summary>
/// This is a simple implementation of our
/// bootstrapper for Ninject. This needs to
/// be
/// </summary>
public abstract class SimpleBootstrapper:IBootstrapper
{
/// <summary>
/// The Ninject-Kernel,
/// our Container in terms
/// of
/// </summary>
private IKernel container;
/// <summary>
/// The list of modules to import.
/// </summary>
private IList<INinjectModule> modules;
/// <summary>
///
/// </summary>
private IViewModelLocator viewModelLocator;
/// <summary>
/// The container (Ninject Kernel)
/// used to bind the types to
/// the interfaces.
/// </summary>
public IKernel Container
{
get
{
return this.container;
}
set
{
this.container = value;
}
}
/// <summary>
/// The ninject modules
/// to be loaded by the
/// container (Ninject Kernel)
/// </summary>
public IList<INinjectModule> Modules
{
get
{
return this.modules;
}
set
{
this.modules = value;
}
}
/// <summary>
/// The ViewModel-Locator
/// that holds the instantiated
/// ViewModels to bind the
/// XAML against.
/// </summary>
public IViewModelLocator ViewModelLocator
{
get
{
return this.viewModelLocator;
}
set
{
this.viewModelLocator = value;
}
}
/// <summary>
/// The standard constructor.
/// </summary>
public SimpleBootstrapper()
{
//Nothing here curretnly.
}
/// <summary>
/// This method is defined
/// as virtual, to enable
/// an entry point for Ninject
/// like stated by Owen on Twitter.
/// </summary>
public virtual void ConfigureBootstrapper()
{
//Not implemented yet.
}
}
}
We will use the ConfigureBootstrapper-Method later, to configure and setup everything we need to work successfully with Ninject.
In the next part, I show you how to put all this stuff together.
Thank you for reading. If you have ideas, or want to see something additional here, let me know. All the code is hosted on GitHub: https://github.com/Injac/WindowsPhone8MVVM
Subscribe to:
Posts (Atom)