IoC and NavigationService implementation

This commit is contained in:
2011-03-25 11:22:57 +02:00
parent 98c8cf3f94
commit f069ee7010
31 changed files with 1139 additions and 73 deletions
@@ -0,0 +1,8 @@
using System;
namespace MicroIoc
{
public class InjectAttribute : Attribute
{
}
}
@@ -0,0 +1,24 @@
using System;
namespace MicroIoc
{
public class ContainerConfiguration : IConfiguration
{
private readonly IMicroIocContainer _container;
public ContainerConfiguration(IMicroIocContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public IConfiguration Configure<T>(InjectedMemberBase injection)
{
var fullName = injection.DeriveFullName<T>();
_container.RegisterInstance(injection.MemberValue.GetType(), injection.MemberValue, fullName);
return this;
}
}
}
@@ -0,0 +1,7 @@
namespace MicroIoc
{
public interface IConfiguration
{
IConfiguration Configure<T>(InjectedMemberBase injection);
}
}
@@ -0,0 +1,16 @@
namespace MicroIoc
{
public class InjectedConstructorParam<T> : InjectedMemberBase
{
public InjectedConstructorParam(string name, T value)
{
MemberName = name;
MemberValue = value;
}
public override string DeriveFullName<TClass>()
{
return typeof (TClass).ConstructorParamPattern(MemberName);
}
}
}
@@ -0,0 +1,10 @@
namespace MicroIoc
{
public abstract class InjectedMemberBase
{
public string MemberName { get; set; }
public object MemberValue { get; set; }
public abstract string DeriveFullName<T>();
}
}
@@ -0,0 +1,16 @@
namespace MicroIoc
{
public class InjectedProperty<T> : InjectedMemberBase
{
public InjectedProperty(string name, T value)
{
MemberName = name;
MemberValue = value;
}
public override string DeriveFullName<TClass>()
{
return typeof(TClass).PropertyPattern(MemberName);
}
}
}
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
namespace MicroIoc
{
public interface IMicroIocContainer
{
/// <summary>
/// Register a type within the container. Useful when registering a type by key, so calls to Resolve(null, key) will work
/// </summary>
/// <typeparam name="T">The type of class being registered</typeparam>
/// <param name="key">If specified, will associate a specific instance for this type</param>
/// <param name="isSingleton">Indicates if the registration should yield a singleton object when resolved</param>
/// <returns>The container, complete with new registration</returns>
IMicroIocContainer Register<T>(string key = null, bool isSingleton = false);
/// <summary>
/// Register an implementation type against an interface or class
/// </summary>
/// <typeparam name="TFrom">The type of interface or class to be registered</typeparam>
/// <typeparam name="TTo">The type of concrete class to be instantiated when <see cref="TFrom" /> is resolved from the container.</typeparam>
/// <param name="key">If specified, will associate a specific instance for this type</param>
/// <param name="isSingleton">Indicates if the registration should yield a singleton object when resolved</param>
/// <returns>The container, complete with new registration</returns>
IMicroIocContainer Register<TFrom, TTo>(string key = null, bool isSingleton = false) where TTo : TFrom;
/// <summary>
/// Register a specific instance of a concrete implementation for an interface or class
/// </summary>
/// <typeparam name="TInterface">The type of interface or class to be registered</typeparam>
/// <param name="instance">The instance to register in the container</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The container, complete with new registration</returns>
IMicroIocContainer RegisterInstance<TInterface>(TInterface instance, string key = null);
/// <summary>
/// Register a specific instance of a concrete implementation for an interface or class
/// </summary>
/// <param name="type">The type of interface or class to be registered</param>
/// <param name="instance">The instance to register in the container</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The container, complete with new registration</returns>
IMicroIocContainer RegisterInstance(Type type, object instance, string key = null);
/// <summary>
/// Resolve an instance of the specified interface (or class) Type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The registered instance if key is specified, or a dynamically instantiated instance, if not</returns>
T Resolve<T>(string key = null);
/// <summary>
/// Try to resolve an instance of the specified interface (or class) Type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>An instance of <typeparamref name="T"/> if registered, or null</returns>
T TryResolve<T>(string key = null) where T : class;
/// <summary>
/// Resolve an instance of the specified interface (or class) Type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The registered instance if key is specified, or a dynamically instantiated instance, if not</returns>
object Resolve(Type type, string key = null);
/// <summary>
/// Try to resolve an instance of the specified interface (or class) Type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>An instance of if registered, or null</returns>
object TryResolve(Type type, string key = null);
/// <summary>
/// Resolve all registered instances of a specified type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <returns>A collection of registered instances. If no instances are registered, returns empty collection, not null</returns>
IEnumerable<T> ResolveAll<T>();
/// <summary>
/// Resolve all registered instances of a specified type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <returns>A collection of registered instances. If no instances are registered, returns empty collection, not null</returns>
IEnumerable<object> ResolveAll(Type type);
/// <summary>
///
/// </summary>
/// <returns></returns>
IConfiguration GetConfiguration();
/// <summary>
/// Create an instance with properties from the container.
/// Only properties attributed [Inject] will be set.
/// </summary>
/// <param name="instance"></param>
void BuildUp(object instance);
}
}
@@ -0,0 +1,299 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MicroIoc;
namespace MicroIoc
{
public class MicroIocContainer : IMicroIocContainer
{
private readonly Dictionary<Tuple<Type, string>, Func<object>> _resolverDictionary
= new Dictionary<Tuple<Type, string>, Func<object>>();
private readonly IList<Type> _registeredSingletons
= new List<Type>();
private readonly Dictionary<Type, object> _singletonInstances
= new Dictionary<Type, object>();
private static readonly string CollectionDefaultKey = Guid.NewGuid().ToString();
#region Register
/// <summary>
/// Register a type within the container. Useful when registering a type by key, so calls to Resolve(null, key) will work
/// </summary>
/// <typeparam name="T">The type of class being registered</typeparam>
/// <param name="key">If specified, will associate a specific instance for this type</param>
/// <param name="isSingleton">Indicates if the registration should yield a singleton object when resolved</param>
/// <returns>The container, complete with new registration</returns>
public IMicroIocContainer Register<T>(string key = null, bool isSingleton = false)
{
return Register<T, T>(key, isSingleton);
}
/// <summary>
/// Register an implementation type against an interface or class
/// </summary>
/// <typeparam name="TFrom">The type of interface or class to be registered</typeparam>
/// <typeparam name="TTo">The type of concrete class to be instantiated when <see cref="TFrom" /> is resolved from the container.</typeparam>
/// <returns>The container, complete with new registration</returns>
public IMicroIocContainer Register<TFrom, TTo>(string key = null, bool isSingleton = false) where TTo : TFrom
{
key = ValueOrDefault(key);
var fromType = typeof(TFrom);
var toType = typeof(TTo);
if (isSingleton)
_registeredSingletons.Add(toType);
_resolverDictionary[new Tuple<Type, string>(fromType, key)] = () => BuildFromType(toType);
return this;
}
/// <summary>
/// Register a specific instance of a concrete implementation for an interface or class
/// </summary>
/// <typeparam name="TInterface">The type of interface or class to be registered</typeparam>
/// <param name="instance">The instance to register in the container</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The container, complete with new registration</returns>
public IMicroIocContainer RegisterInstance<TInterface>(TInterface instance, string key = null)
{
return RegisterInstance(typeof (TInterface), instance, key);
}
public IMicroIocContainer RegisterInstance(Type type, object instance, string key=null)
{
key = ValueOrDefault(key);
_resolverDictionary[new Tuple<Type, string>(type, key)] = () => instance;
return this;
}
#endregion
#region Resolve
/// <summary>
/// Resolve an instance of the specified interface (or class) Type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The registered instance if key is specified, or a dynamically instantiated instance, if not</returns>
public T Resolve<T>(string key = null)
{
return (T) Resolve(typeof (T), key);
}
/// <summary>
/// Try to resolve an instance of the specified interface (or class) Type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>An instance of <typeparamref name="T"/> if registered, or null</returns>
public T TryResolve<T>(string key) where T : class
{
return (T) TryResolve(typeof (T), key);
}
/// <summary>
/// Resolve an instance of the specified interface (or class) Type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>The registered instance if key is specified, or a dynamically instantiated instance, if not</returns>
public object Resolve(Type type, string key = null)
{
var result = ResolveCore(type, key);
BuildUp(result);
return result;
}
/// <summary>
/// Try to resolve an instance of the specified interface (or class) Type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <param name="key">(Optional) a key to specify the instance within the container</param>
/// <returns>An instance of if registered, or null</returns>
public object TryResolve(Type type, string key)
{
try
{
return Resolve(type, key);
}
catch
{
return null;
}
}
/// <summary>
/// Resolve all registered instances of a specified type
/// </summary>
/// <typeparam name="T">The type of interface or class to be resolved</typeparam>
/// <returns>A collection of registered instances. If no instances are registered, returns empty collection, not null</returns>
public IEnumerable<T> ResolveAll<T>()
{
var allObjects = ResolveAll(typeof (T));
return allObjects.Select(obj => (T) obj);
}
/// <summary>
/// Resolve all registered instances of a specified type
/// </summary>
/// <param name="type">The type of interface or class to be resolved</param>
/// <returns>A collection of registered instances. If no instances are registered, returns empty collection, not null</returns>
public IEnumerable<object> ResolveAll(Type type)
{
return _resolverDictionary.Keys
.Where(key => key.Item1 == type)
.Select(t => _resolverDictionary[t]());
}
#endregion
/// <summary>
/// Create an instance with properties from the container.
/// Only properties attributed [Inject] will be set.
/// </summary>
/// <param name="instance"></param>
public void BuildUp(object instance)
{
var propertyInfoCollection = instance.GetType().GetProperties();
foreach (var propertyInfo in propertyInfoCollection)
{
var info = propertyInfo;
if (!info.GetCustomAttributes(typeof(InjectAttribute), false).Any()) continue;
object property = null;
try
{
var fullPropertyName = string.Format("{0}.{1}", instance.GetType().FullName, info.Name);
property = Resolve(null, fullPropertyName);
}
catch (Exception)
{
property = Resolve(info.PropertyType);
}
finally
{
info.SetValue(instance, property, null);
}
}
}
public IConfiguration GetConfiguration()
{
return new ContainerConfiguration(this);
}
#region Private helper methods
private object ResolveCore(Type type, string key)
{
if (type == null)
{
type = DeriveType(key);
if (type == null)
throw new ResolutionException("Failed to Derive type for " + key);
}
key = ValueOrDefault(key);
return _resolverDictionary.ContainsKey(new Tuple<Type, string>(type, key))
? _resolverDictionary[new Tuple<Type, string>(type, key)]()
: BuildFromType(type);
}
private Type DeriveType(string key)
{
var result = GetTypeFromContainer(key);
if (result != null) return result;
// Not in the container? Try the Assembly
return Assembly.GetExecutingAssembly()
.GetTypes()
.SingleOrDefault(t => t.Name == key);
}
private Type GetTypeFromContainer(string key)
{
var tuple = _resolverDictionary
.Keys
.FirstOrDefault(t => t.Item2 == key);
return (tuple == null)
? null
: tuple.Item1;
}
private object BuildFromType(Type type)
{
if (_registeredSingletons.Contains(type))
{
object instance;
if (_singletonInstances.TryGetValue(type, out instance))
return instance;
instance = InstantiateInstance(type);
_singletonInstances[type] = instance;
return instance;
}
return InstantiateInstance(type);
}
private object InstantiateInstance(Type type)
{
var constructor = type.GetConstructors()
.OrderByDescending(c => c.GetParameters().Length)
.FirstOrDefault();
if (constructor == null)
throw new ResolutionException("Could not locate a constructor for " + type.FullName);
var constructorParams = new List<object>(constructor.GetParameters().Length);
foreach (var parameterInfo in constructor.GetParameters())
{
object parameter=null;
try
{
string key = type.ConstructorParamPattern(parameterInfo.Name);
parameter = Resolve(null, key);
}
catch (Exception)
{
parameter = Resolve(parameterInfo.ParameterType);
}
finally
{
constructorParams.Add(parameter);
}
}
try
{
return constructor.Invoke(constructorParams.ToArray());
}
catch (Exception exception)
{
throw new ResolutionException("Failed to resolve " + type.Name, exception);
}
}
private static string ValueOrDefault(string key)
{
if (key != null) key = key.Trim();
return string.IsNullOrEmpty(key)
? CollectionDefaultKey
: key;
}
#endregion
}
}
@@ -0,0 +1,13 @@
using System;
namespace MicroIoc
{
public class ResolutionException : Exception
{
public ResolutionException(string message)
: base(message) { }
public ResolutionException(string message, Exception innerException)
: base(message, innerException) { }
}
}
@@ -0,0 +1,37 @@
using System;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MicroIoc;
using System.Linq.Expressions;
namespace MicroIoc
{
public static class ConfigurationExtensions
{
public static IConfiguration Property<T, TProp>(this IConfiguration configuration, Expression<Func<T, TProp>> propertyExpression, TProp value)
{
var memberExpression = propertyExpression.Body as MemberExpression;
if (memberExpression == null)
throw new ArgumentException("propertyExpression is not a valid member expression");
var propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("propertyExpression is not a valid property on the class");
return configuration.Configure<T>(new InjectedProperty<TProp>(propertyInfo.Name, value));
}
public static IConfiguration ConstructorParam<T, TParam>(this IConfiguration configuration, string name, TParam value)
{
return configuration.Configure<T>(new InjectedConstructorParam<TParam>(name, value));
}
}
}
@@ -0,0 +1,17 @@
using System;
namespace MicroIoc
{
public static class PatternExtensions
{
public static string PropertyPattern(this Type type, string memberName)
{
return type.FullName + "." + memberName;
}
public static string ConstructorParamPattern(this Type type, string memberName)
{
return type.FullName + "#" + memberName;
}
}
}
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.20506</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{23F63AE9-A436-4B27-9113-4142C09ADD08}</ProjectGuid>
<ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MicroIoc</RootNamespace>
<AssemblyName>MicroIoc</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
<TargetFrameworkProfile>WindowsPhone</TargetFrameworkProfile>
<TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
<SilverlightApplication>false</SilverlightApplication>
<ValidateXaml>true</ValidateXaml>
<ThrowErrorsInValidation>true</ThrowErrorsInValidation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Bin\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>Bin\Release</OutputPath>
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Windows" />
<Reference Include="system" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="System.Net" />
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\ContainerConfiguration.cs" />
<Compile Include="Configuration\IConfiguration.cs" />
<Compile Include="Configuration\InjectedConstructorParam.cs" />
<Compile Include="Configuration\InjectedMemberBase.cs" />
<Compile Include="Configuration\InjectedProperty.cs" />
<Compile Include="Container\IMicroIocContainer.cs" />
<Compile Include="Attributes\InjectAttribute.cs" />
<Compile Include="Container\MicroIocContainer.cs" />
<Compile Include="Extensions\ConfigurationExtensions.cs" />
<Compile Include="Extensions\PatternExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Exceptions\ResolutionException.cs" />
<Compile Include="Tuple.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
<ProjectExtensions />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MicroIoc")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("MicroIoc")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("dafbba88-e0f6-4b77-94de-a70fdf20bf46")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.1.0.0")]
[assembly: AssemblyFileVersion("0.1.0.0")]
+52
View File
@@ -0,0 +1,52 @@
namespace MicroIoc
{
public class Tuple<T1, T2>
{
public Tuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public bool Equals(Tuple<T1, T2> other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Equals(other.Item1, Item1) && Equals(other.Item2, Item2);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof(Tuple<T1, T2>))
{
return false;
}
return Equals((Tuple<T1, T2>)obj);
}
public override int GetHashCode()
{
unchecked
{
return (Item1.GetHashCode() * 397) ^ Item2.GetHashCode();
}
}
}
}
+5 -1
View File
@@ -34,6 +34,9 @@ namespace MyFriendsAround.WP7
// Phone-specific initialization
InitializePhoneApplication();
//register ViewModelLocator
Container.Instance.RegisterInstance(typeof(ViewModelLocator), "ViewModelLocator");
}
// Code to execute when the application is launching (eg, from Start)
@@ -58,7 +61,8 @@ namespace MyFriendsAround.WP7
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
ViewModelLocator.Cleanup();
ViewModelLocator locator = Container.Instance.Resolve<ViewModelLocator>();
locator.Cleanup();
}
// Code to execute if a navigation fails
@@ -0,0 +1,23 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
namespace MyFriendsAround.WP7.Helpers.Navigation
{
public interface IPageNavigation
{
event NavigatingCancelEventHandler Navigating;
object CurrentContext { get; }
void NavigateTo(Uri pageUri);
void NavigateTo(Uri pageUri, object context);
void GoBack();
}
}
@@ -0,0 +1,82 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
namespace MyFriendsAround.WP7.Helpers.Navigation
{
public class PageNavigation : IPageNavigation
{
private PhoneApplicationFrame mainFrame;
private bool EnsureMainFrame()
{
if (mainFrame != null)
{
return true;
}
mainFrame = Application.Current.RootVisual as PhoneApplicationFrame;
if (mainFrame != null)
{
// Could be null if the app runs inside a design tool
mainFrame.Navigating += (s, e) =>
{
if (Navigating != null)
{
Navigating(s, e);
}
};
return true;
}
return false;
}
#region IPageNavigation implementation
public event NavigatingCancelEventHandler Navigating;
private object currentContext;
public object CurrentContext
{
get { return this.currentContext; }
}
public void NavigateTo(Uri pageUri)
{
if (pageUri == null)
throw new ArgumentNullException("uri");
if (EnsureMainFrame())
this.NavigateTo(pageUri, null);
}
public void NavigateTo(Uri pageUri, object context)
{
if (pageUri == null)
throw new ArgumentNullException("uri");
if (EnsureMainFrame())
{
this.currentContext = context;
mainFrame.Navigate(pageUri);
}
}
public void GoBack()
{
if (EnsureMainFrame() && mainFrame.CanGoBack)
{
mainFrame.GoBack();
}
}
#endregion
}
}
@@ -116,7 +116,12 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="MainPage.xaml.cs">
<Compile Include="Helpers\Navigation\IPageNavigation.cs" />
<Compile Include="Helpers\Navigation\PageNavigation.cs" />
<Compile Include="Views\AboutPage.xaml.cs">
<DependentUpon>AboutPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -126,8 +131,11 @@
<Compile Include="Tests\Tests1.cs" />
<Compile Include="Utils\Identification.cs" />
<Compile Include="Utils\SerializationHelper.cs" />
<Compile Include="ViewModel\Container.cs" />
<Compile Include="ViewModel\AboutViewModel.cs" />
<Compile Include="ViewModel\MainViewModel.cs" />
<Compile Include="ViewModel\PushPinModel.cs" />
<Compile Include="ViewModel\ViewModelBase.cs" />
<Compile Include="ViewModel\ViewModelLocator.cs" />
</ItemGroup>
<ItemGroup>
@@ -135,7 +143,11 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Page Include="Views\AboutPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
@@ -158,12 +170,11 @@
<Content Include="icons\appbar.questionmark.rest.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="README_FIRST.txt" />
<Content Include="SplashScreenImage.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Resource Include="Toolkit.Content\ApplicationBar.Cancel.png" />
<Resource Include="Toolkit.Content\ApplicationBar.Check.png" />
<Content Include="Toolkit.Content\ApplicationBar.Cancel.png" />
<Content Include="Toolkit.Content\ApplicationBar.Check.png" />
</ItemGroup>
<ItemGroup>
<Folder Include="Model\" />
@@ -176,6 +187,10 @@
<Project>{A128812A-1249-4562-BDF4-5E17951B8434}</Project>
<Name>GpsEmulatorClient</Name>
</ProjectReference>
<ProjectReference Include="..\Libs\MicroIoc\MicroIoc.Core\MicroIoc.Core.csproj">
<Project>{23F63AE9-A436-4B27-9113-4142C09ADD08}</Project>
<Name>MicroIoc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Libs\Phone7.Fx.Preview\Phone7.Fx.Preview.csproj">
<Project>{B55A0F90-2B5A-4C4B-88F4-013AA1629866}</Project>
<Name>Phone7.Fx.Preview</Name>
@@ -17,7 +17,7 @@
<Capability Name="ID_CAP_IDENTITY_USER" />
</Capabilities>
<Tasks>
<DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>
<DefaultTask Name ="_default" NavigationPage="Views\MainPage.xaml"/>
</Tasks>
<Tokens>
<PrimaryToken TokenID="MyFriendsAround.WP7Token" TaskName="_default">
@@ -1,3 +0,0 @@
For the Silverlight for Windows Phone Toolkit make sure that you have
marked the icons in the "Toolkit.Content" folder as content. That way they
can be used as the icons for the ApplicationBar control.
@@ -28,5 +28,6 @@ namespace MyFriendsAround.WP7.Utils
{
return JsonConvert.SerializeObject(obj);
}
}
}
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Device.Location;
using System.Net;
using System.ServiceModel.Channels;
using System.Windows;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using Hammock;
using Hammock.Serialization;
using Microsoft.Phone.Controls;
using Microsoft.Silverlight.Testing;
using MyFriendsAround.Common.Entities;
using MyFriendsAround.WP7.Service;
using MyFriendsAround.WP7.Utils;
using Newtonsoft.Json;
namespace MyFriendsAround.WP7.ViewModel
{
public class AboutViewModel : ViewModelBase
{
public string ApplicationTitle
{
get
{
return "MyFriendsAround";
}
}
public string PageName
{
get
{
return "About";
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public AboutViewModel()
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
// Code runs "for real"
}
}
public string AppBarTextAbout {
get { return "About"; }
}
public string AppBarTextPublish
{
get { return "Publish"; }
}
}
}
@@ -0,0 +1,40 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MicroIoc;
namespace MyFriendsAround.WP7.ViewModel
{
public sealed class Container
{
Container()
{
}
public static IMicroIocContainer Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as before field init
static Nested()
{
}
internal static readonly IMicroIocContainer instance =
new MicroIocContainer();
}
}
}
@@ -51,14 +51,6 @@ namespace MyFriendsAround.WP7.ViewModel
}
}
public string Welcome
{
get
{
return "Welcome to MVVM Light";
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
@@ -68,6 +60,7 @@ namespace MyFriendsAround.WP7.ViewModel
PublishLocationCommand = new RelayCommand(() => PublishLocationAction());
DisplayAboutCommand = new RelayCommand(() => DisplayAbout());
InputBoxCommand = new RelayCommand(() => InputBox());
NavigateToAboutCommand = new RelayCommand(() => NavigateToAbout());
if (IsInDesignMode)
{
@@ -82,6 +75,12 @@ namespace MyFriendsAround.WP7.ViewModel
}
private void NavigateToAbout()
{
//
this.PageNav.NavigateTo(new Uri("/Views/AboutPage.xaml", UriKind.Relative));
}
private void InputBox()
{
MessageBox.Show("Input box");
@@ -102,7 +101,7 @@ namespace MyFriendsAround.WP7.ViewModel
//f.LocationStr
result.Add(new PushPinModel()
{
PinSource = "ApplicationIcon.png",
PinSource = "/ApplicationIcon.png",
Location = new GeoCoordinate(f.Latitude, f.Longitude)
});
});
@@ -161,10 +160,17 @@ namespace MyFriendsAround.WP7.ViewModel
}
}
public RelayCommand PublishLocationCommand { get; set; }
public RelayCommand DisplayAboutCommand { get; set; }
public RelayCommand InputBoxCommand { get; set; }
public ICommand PublishLocationCommand { get; set; }
public ICommand DisplayAboutCommand { get; set; }
public ICommand InputBoxCommand { get; set; }
public ICommand NavigateToAboutCommand
{
get;
private set;
}
public string MyName { get; set; }
public string AppBarTextAbout {
@@ -0,0 +1,43 @@
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MyFriendsAround.WP7.Helpers.Navigation;
namespace MyFriendsAround.WP7.ViewModel
{
public class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase
{
private object context;
public object Context
{
get { return context; }
set
{
if (context == value)
return;
context = value;
RaisePropertyChanged("Context");
}
}
/// <summary>
/// Gets PageNavigation from Container
/// </summary>
public IPageNavigation PageNav
{
get
{
IPageNavigation pageNav =
(IPageNavigation)Container.Instance.Resolve(typeof(PageNavigation), "PageNavigation");
return pageNav;
}
}
}
}
@@ -14,6 +14,7 @@
DataContext="{Binding Source={x:Static vm:ViewModelLocatorTemplate.ViewModelNameStatic}}"
*/
using MyFriendsAround.WP7.Helpers.Navigation;
namespace MyFriendsAround.WP7.ViewModel
{
/// <summary>
@@ -55,81 +56,79 @@ namespace MyFriendsAround.WP7.ViewModel
/// </summary>
public class ViewModelLocator
{
private static MainViewModel _main;
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
////if (ViewModelBase.IsInDesignModeStatic)
////{
//// // Create design time view models
////}
////else
////{
//// // Create run time view models
////}
CreateMain();
}
/// <summary>
/// Gets the Main property.
/// </summary>
public static MainViewModel MainStatic
{
get
if (ViewModelBase.IsInDesignModeStatic)
{
if (_main == null)
{
CreateMain();
}
return _main;
// Create design time view models
}
else
{
//Register PageNavigation - only if not design time
Container.Instance.RegisterInstance(typeof(PageNavigation), "PageNavigation");
// Create run time view models
}
Container.Instance.RegisterInstance(typeof(MainViewModel), "MainViewModel");
Container.Instance.RegisterInstance(typeof(AboutViewModel), "AboutViewModel");
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return MainStatic;
MainViewModel mainViewModel = GetViewModel<MainViewModel>();
return mainViewModel;
}
}
/// <summary>
/// Provides a deterministic way to delete the Main property.
/// Gets the About property.
/// </summary>
public static void ClearMain()
public AboutViewModel About
{
_main.Cleanup();
_main = null;
}
/// <summary>
/// Provides a deterministic way to create the Main property.
/// </summary>
public static void CreateMain()
{
if (_main == null)
get
{
_main = new MainViewModel();
AboutViewModel aboutViewModel = GetViewModel<AboutViewModel>();
return aboutViewModel;
}
}
/// <summary>
/// Cleans up all the resources.
/// </summary>
public static void Cleanup()
public void Cleanup()
{
ClearMain();
MainViewModel mainViewModel = GetViewModel<MainViewModel>();
mainViewModel.Cleanup();
AboutViewModel aboutViewModel = GetViewModel<AboutViewModel>();
aboutViewModel.Cleanup();
}
#region Local Helpers
private T GetViewModel<T>() where T : ViewModelBase
{
// Create a new view model
T vm = Container.Instance.Resolve<T>();
//Assign the Context from PageNavigation to Context property of the ViewModelBase
vm.Context = vm.PageNav.CurrentContext;
return vm;
}
#endregion
}
}
@@ -0,0 +1,35 @@
<phone:PhoneApplicationPage
x:Class="MyFriendsAround.WP7.Views.AboutPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
DataContext="{Binding About, Source={StaticResource Locator}}"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="{Binding Path=ApplicationTitle}" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="{Binding Path=PageName}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
</Grid>
</phone:PhoneApplicationPage>
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
namespace MyFriendsAround.WP7.Views
{
public partial class AboutPage : PhoneApplicationPage
{
public AboutPage()
{
InitializeComponent();
}
}
}
@@ -53,11 +53,6 @@
Grid.Row="1"
Margin="0,0,0,70">
<TextBlock Text="{Binding Welcome}"
Style="{StaticResource PhoneTextNormalStyle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="40" />
<!--<Button Content="Publish"
HorizontalAlignment="Left" Margin="6,0,0,6" Name="btnPublishLocation"
Width="468"
@@ -104,7 +99,7 @@
<Preview:BindableApplicationBarIconButton Command="{Binding PublishLocationCommand}"
IconUri="/icons/appbar.publish.png"
Text="{Binding AppBarTextPublish}" />
<Preview:BindableApplicationBarIconButton Command="{Binding DisplayAboutCommand}"
<Preview:BindableApplicationBarIconButton Command="{Binding NavigateToAboutCommand}"
IconUri="/icons/appbar.questionmark.rest.png"
Text="{Binding AppBarTextAbout}" />
+18
View File
@@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GpsEmulatorPhoneTestClient"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Phone7.Fx.Preview", "Libs\Phone7.Fx.Preview\Phone7.Fx.Preview.csproj", "{B55A0F90-2B5A-4C4B-88F4-013AA1629866}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroIoc.Core", "Libs\MicroIoc\MicroIoc.Core\MicroIoc.Core.csproj", "{23F63AE9-A436-4B27-9113-4142C09ADD08}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -222,6 +224,21 @@ Global
{B55A0F90-2B5A-4C4B-88F4-013AA1629866}.Tests|Mixed Platforms.ActiveCfg = Release|Any CPU
{B55A0F90-2B5A-4C4B-88F4-013AA1629866}.Tests|Mixed Platforms.Build.0 = Release|Any CPU
{B55A0F90-2B5A-4C4B-88F4-013AA1629866}.Tests|x86.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Debug|x86.ActiveCfg = Debug|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Release|Any CPU.Build.0 = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Release|x86.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Tests|Any CPU.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Tests|Any CPU.Build.0 = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Tests|Mixed Platforms.ActiveCfg = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Tests|Mixed Platforms.Build.0 = Release|Any CPU
{23F63AE9-A436-4B27-9113-4142C09ADD08}.Tests|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -231,5 +248,6 @@ Global
{A128812A-1249-4562-BDF4-5E17951B8434} = {340549A1-45EA-4B49-B194-347C0078BAD8}
{BF7316A8-A2C5-4176-8D7F-672AD12F474D} = {340549A1-45EA-4B49-B194-347C0078BAD8}
{B55A0F90-2B5A-4C4B-88F4-013AA1629866} = {340549A1-45EA-4B49-B194-347C0078BAD8}
{23F63AE9-A436-4B27-9113-4142C09ADD08} = {340549A1-45EA-4B49-B194-347C0078BAD8}
EndGlobalSection
EndGlobal