Adding SettingsData support to ViewModel with MVVM Light in WinRT

In the previous Post, I have spoken about a solution for DialogMessaging service. Now I would you like propose another solution for read and write data from the LocalSettings or RoamingSettings using IOC design pattern and MVVM Light toolkit.

So, Let’s start with the definition of an Interface that allows the support to the Local/Remote Settings.

	
public interface ISettingsDataService
{
	T GetItem<T>(string container, string id);

	IEnumerable GetItems<T>(string container);

	void SetValue<T>(string container, string id, T data);

	IEnumerable GetEntities<T>(string container)
		where T: new()

	void SetEntity<T>(string conatiner, T entity)
		where T: new()		
}

Now we have to move to the implementation:

public class SettingsDataService: ISettingsDataService
{
	private ApplicationDataContainer settingsContainer;

	public SettingsStoreService(ApplicationDataContainer applicationDataContainer) 
	{
		this.settingsContainer = applicationDataContainer; 
	}	 

	public T GetItem<T>(string container, string id)
	{
		if (container == null)
			throw new ArgumentNullException("Container cannot be null.");

		if (id == null)
			throw new ArgumentNullException("Id cannot be null");

		ApplicationDataContainer dataContainer = 
				settingsContainer.CreateContainer(container, ApplicationDataCreateDisposition.Always);

		var value = dataContainer.Values.ContainsKey(id)? dataContainer.Values[id]: null;
		if (value == null) return default(T);
		return (T)value;
	}

	public IEnumerable GetItems<T>(string container) 
	{
		if (container == null)
			throw new ArgumentNullException("Container cannot be null");

		ApplicationDataContainer dataContainer = 
			settingsContainer.CreateContainer(container, ApplicationDataCreateDisposition.Always);

		var values = new List();
		foreach (var value in dataContainer.Values)
			values.Add((T)value.Value);
		return values;
	}

	public IEnumerable GetEntities<T>(string container) where T : new()
	{
		if (container == null) 
		throw new ArgumentNullException("Container cannot be null");

		ApplicationDataContainer dataContainer = 
		settingsContainer.CreateContainer(container, ApplicationDataCreateDisposition.Always);

		var values = new List();	 
		foreach (var compositeValue in dataContainer.Values)
		{
			var entity = CreateEntity((ApplicationDataCompositeValue)compositeValue.Value);
			values.Add(entity);
		}
		return values;	 
	}

	public void SetValue<T>(string container, string id, T value)
	{	 
		if (container == null)
			throw new ArgumentNullException("Container cannot be null");

		if (string.IsNullOrEmpty(id)) 
			throw new ArgumentNullException("Id cannot be null");

		if (value == null)
			throw new ArgumentNullException("Value cannot be null");

		ApplicationDataContainer dataContainer = 
			settingsContainer.CreateContainer(container, ApplicationDataCreateDisposition.Always);
		dataContainer.Values[id] = value;	 
	}

	public void SetEntity<T>(string container, string id, T value) where T : new()
	{
		if (container == null)	 
			throw new ArgumentNullException("Container cannot be null");

		if (string.IsNullOrEmpty(id)) 
			throw new ArgumentNullException("Id cannot be null");

		if (value == null)		 
			throw new ArgumentNullException("Value cannot be null");

		ApplicationDataContainer dataContainer = 
			settingsContainer.CreateContainer(container, ApplicationDataCreateDisposition.Always);

		ApplicationDataCompositeValue compositeValue = GetCompositeValue(value); 
		dataContainer.Values[id] = compositeValue;	 
	} 

	private T CreateEntity<T>(ApplicationDataCompositeValue compositeValue) 
		where T : new()
	{
		var entity = new T(); 
		if (entity != null) 
		{ 
			foreach (var keyValue in compositeValue)
				entity.GetType().GetRuntimeProperty(keyValue.Key).SetValue(entity, keyValue.Value);

		} 
		return entity;	 
	}

	private ApplicationDataCompositeValue GetCompositeValue(object entity)
	{
		var compositeValue = new ApplicationDataCompositeValue();
		var entitySerializable = entity.GetType()
									   .GetRuntimeProperties()
									   .Where(p => p.PropertyType.GetTypeInfo()
									   .IsSerializable
		foreach (var property in entitySerializable))
			compositeValue[property.Name] = entity.GetType().GetRuntimeProperty(property.Name).GetValue(entity);
		return compositeValue; 
	}  
}

And then, we need to register this service when the app starts.
So, define the following method in the ViewModelLocator class:

public class ViewModelLocator
{
	public ViewModelLocator()
	{
		 ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
		 if (!ViewModelBase.IsInDesignModeStatic)
		 { 
			Registers();
		 } 
	}

	public void Registers()
	{
		SimpleIoc.Default.Register(() => new SettingsDataService(ApplicationData.Current.LocalSettings));
	}
}

In the viewmodel, where we need the SettingsDataService we use dependency injection in this way:

public class MainViewModel: ViewModelBase
{
	public MainViewModel(ISettingsDataService settingsDataService)
	{
		//Get a simple value from the LocalStore using ISettingsDataService
		var title = settingsDataService.GetItem<string>("ContainerStoreApp", "TitleApp");

		//Set a simple Entity
		MyClass c = new MyClass();
		c.MyProperty = "MyValue";
		c.MyComplexProperty = "MyComplexProperty";

		settingsDataService.SetEntity<MyClass>("ContainerStoreApp", c);
	}
}

In this way we are able to interact with the SettingsData using IOC and MVVM Light.

Enjoy
Maurizio

MetroZip App for Windows Store – Release 1

MetroZip
E’ ufficialmente nello store la nuova App MetroZip, l’Applicazione che vi permette di create e gestire i vostri archivi compressi in formato zip con tutta comodità.

Quali sono le nuove funzionalità? MetroZip consentirà di:
– creare un nuovo archivio in formato zip
– aprire un archivio zip
– aggiungere files o folders ad un archivio esistente
– condividere via email o in cloud un archivio
– aprire in preview un file presente in un archivio
– estrarre il conteuto di un arichivio compresso

Ecco il link: http://apps.microsoft.com/webpdp/it-IT/app/metrozipfiles/4c7f9047-e2f4-4a4e-83ae-668ba65ae8f1

Maurizio

Windows 8, WinRT, MVVM and NavigationService

Ciao a tutti,
oggi inizieremo con una serie di post/articoli che parleranno di come applicare MVVM alle Windows 8 Apps.

Chi viene dallo sviluppo di Applicazioni per Windows Phone si sarà già imbattuto e quindi saprà bene come risolvere il problema del NavigationService.

Il NavigationService è quella classe che ci permette di effettuare la navigazione in stile browser nelle nostre applicazioni Windows 8 e Windows Phone (per maggiori dettagli sulla classe visitate il link su MSDN).

Normalmente utilizzeremo il NavigationService quando abbiamo la necessità di cambiare pagina magari al variare di una Proprietà piuttosto che sull’azione associata ad un determinato comando.
L’unico problema che salta subito all’occhio è che il NavigationService è accessibile solo tramite il Code Behind della pagina e quindi non accessibile dal nostro ViewModel.

Per risolvere questo problema ci sono diverse soluzioni, la più elegante è quella di implementare un wrapper del NavigationService… ecco qui un snippet di esempio:

//Interfaccia INavigationService
public interface INavigationService
{
void GoBack();
void GoForward();
bool Navigate(object parameter = null);
bool Navigate(Type source, object parameter = null);
}

//NavigationHelper
public class NavigationService : INavigationService
{
private Frame rootFrame { get; set; }

//Qui passeremo come parametro il Frame initializzato nel App.cs
public NavigationHelper(Frame rootFrame)
{
this.rootFrame = rootFrame;
}

public void GoBack()
{
this.rootFrame.GoBack();
}

public void GoForward()
{
this.rootFrame.GoForward();
}

public bool Navigate(object parameter = null)
{
return this.rootFrame.Navigate(typeof(T), parameter);
}

public bool Navigate(Type source, object parameter = null)
{
return this.Navigate(source, parameter);
}
}

Quindi, abbiamo definito un’interfaccia che in sostanza espone le stesse funzionalità di navigazione che avremmo a disposizione nel NavigationService presente nel Code Behind e di seguito la sua implementazione.

Ora non ci rimane che inizializzare il nostro NavigationService nell’App.xaml.cs tramite Dependency Injection (IOC).
Per quanto rigurda IOC possiamo utilizzare qualsiasi soluzione compatibile con WinRT, io come sempre consiglio Galasoft Toolkit di Laurent Bugnion.

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
var rootFrame = new Frame();
if (args.PreviousExecutionState == ApplicationExecutionState.Running)
{
Window.Current.Activate();
return;
}

if (args.PreviousExecutionState == ApplicationExecutionState.Terminated || args.PreviousExecutionState==ApplicationExecutionState.NotRunning)
{
SimpleIoc.Default.Register(typeof (INavigationService), new NavigationService(rootFrame));
}

if (!rootFrame.Navigate(typeof(MainPage)))
{
throw new Exception("Failed to create initial page");
}

// Place the frame in the current Window and ensure that it is active
Window.Current.Content = rootFrame;
Window.Current.Activate();
}

Nell’esempio andiamo a registrare l’istanza del NavigationService nel momento in cui l’App si trova diciamo “In Stato di Fermo” 😀

SimpleIoc” fa riferimento all’utilizzo del Galasoft Toolkit dove di “default” introduce il ViewModelLocator con un’implementazione di IOC chiamata appunto SimpleIoc.

Nei nostri ViewModel avremo così a disposizione il nostro NavigationService:

protected INavigationService navigationService;

public MyViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
}

A questo punto non vi rimane che divertirvi con i vostri ViewModel e le vostre Apps di Windows 8 😀

Credo di aver raccontato tutto 😀
Buon Windows 8 Apps!!!

Maurizio

MetroNote App for Windows Store – Release 2

MetroNote App for Windows 8 Store
E’ ufficialmente pubblicata la nuova major release di MetroNote, l’Applicazione che permette la completa gestione dei vostri Post-it/Memo che ora è diventata GRATUITA.

Quali sono le nuove funzionalità? MetroNote consentirà di:
– cambiare tema (“metal” o “wood”) dello sfondo
– cambiare il colore delle note
– inserire un mark sulle note più importanti
– condividere le note tramite la Share Charm
– aggiungere le note alla Start
… e altro ancora! Aspettate e vedrete!

Ecco il link per vederla sul Windows Store: MetroNote

Maurizio