diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Attributes/InjectAttribute.cs b/main/Libs/MicroIoc/MicroIoc.Core/Attributes/InjectAttribute.cs new file mode 100644 index 0000000..3fb49a6 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Attributes/InjectAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace MicroIoc +{ + public class InjectAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Configuration/ContainerConfiguration.cs b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/ContainerConfiguration.cs new file mode 100644 index 0000000..64e213a --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/ContainerConfiguration.cs @@ -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(InjectedMemberBase injection) + { + var fullName = injection.DeriveFullName(); + _container.RegisterInstance(injection.MemberValue.GetType(), injection.MemberValue, fullName); + return this; + } + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Configuration/IConfiguration.cs b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/IConfiguration.cs new file mode 100644 index 0000000..3b79ba0 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/IConfiguration.cs @@ -0,0 +1,7 @@ +namespace MicroIoc +{ + public interface IConfiguration + { + IConfiguration Configure(InjectedMemberBase injection); + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedConstructorParam.cs b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedConstructorParam.cs new file mode 100644 index 0000000..3db0dad --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedConstructorParam.cs @@ -0,0 +1,16 @@ +namespace MicroIoc +{ + public class InjectedConstructorParam : InjectedMemberBase + { + public InjectedConstructorParam(string name, T value) + { + MemberName = name; + MemberValue = value; + } + + public override string DeriveFullName() + { + return typeof (TClass).ConstructorParamPattern(MemberName); + } + } +} \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedMemberBase.cs b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedMemberBase.cs new file mode 100644 index 0000000..b575360 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedMemberBase.cs @@ -0,0 +1,10 @@ +namespace MicroIoc +{ + public abstract class InjectedMemberBase + { + public string MemberName { get; set; } + public object MemberValue { get; set; } + + public abstract string DeriveFullName(); + } +} \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedProperty.cs b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedProperty.cs new file mode 100644 index 0000000..c4f5c8a --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Configuration/InjectedProperty.cs @@ -0,0 +1,16 @@ +namespace MicroIoc +{ + public class InjectedProperty : InjectedMemberBase + { + public InjectedProperty(string name, T value) + { + MemberName = name; + MemberValue = value; + } + + public override string DeriveFullName() + { + return typeof(TClass).PropertyPattern(MemberName); + } + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Container/IMicroIocContainer.cs b/main/Libs/MicroIoc/MicroIoc.Core/Container/IMicroIocContainer.cs new file mode 100644 index 0000000..cf9644c --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Container/IMicroIocContainer.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; + +namespace MicroIoc +{ + public interface IMicroIocContainer + { + /// + /// Register a type within the container. Useful when registering a type by key, so calls to Resolve(null, key) will work + /// + /// The type of class being registered + /// If specified, will associate a specific instance for this type + /// Indicates if the registration should yield a singleton object when resolved + /// The container, complete with new registration + IMicroIocContainer Register(string key = null, bool isSingleton = false); + + /// + /// Register an implementation type against an interface or class + /// + /// The type of interface or class to be registered + /// The type of concrete class to be instantiated when is resolved from the container. + /// If specified, will associate a specific instance for this type + /// Indicates if the registration should yield a singleton object when resolved + /// The container, complete with new registration + IMicroIocContainer Register(string key = null, bool isSingleton = false) where TTo : TFrom; + + /// + /// Register a specific instance of a concrete implementation for an interface or class + /// + /// The type of interface or class to be registered + /// The instance to register in the container + /// (Optional) a key to specify the instance within the container + /// The container, complete with new registration + IMicroIocContainer RegisterInstance(TInterface instance, string key = null); + + /// + /// Register a specific instance of a concrete implementation for an interface or class + /// + /// The type of interface or class to be registered + /// The instance to register in the container + /// (Optional) a key to specify the instance within the container + /// The container, complete with new registration + IMicroIocContainer RegisterInstance(Type type, object instance, string key = null); + + /// + /// Resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// The registered instance if key is specified, or a dynamically instantiated instance, if not + T Resolve(string key = null); + + /// + /// Try to resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// An instance of if registered, or null + T TryResolve(string key = null) where T : class; + + /// + /// Resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// The registered instance if key is specified, or a dynamically instantiated instance, if not + object Resolve(Type type, string key = null); + + /// + /// Try to resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// An instance of if registered, or null + object TryResolve(Type type, string key = null); + + /// + /// Resolve all registered instances of a specified type + /// + /// The type of interface or class to be resolved + /// A collection of registered instances. If no instances are registered, returns empty collection, not null + IEnumerable ResolveAll(); + + /// + /// Resolve all registered instances of a specified type + /// + /// The type of interface or class to be resolved + /// A collection of registered instances. If no instances are registered, returns empty collection, not null + IEnumerable ResolveAll(Type type); + + /// + /// + /// + /// + IConfiguration GetConfiguration(); + + /// + /// Create an instance with properties from the container. + /// Only properties attributed [Inject] will be set. + /// + /// + void BuildUp(object instance); + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Container/MicroIocContainer.cs b/main/Libs/MicroIoc/MicroIoc.Core/Container/MicroIocContainer.cs new file mode 100644 index 0000000..8f1a5cd --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Container/MicroIocContainer.cs @@ -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, Func> _resolverDictionary + = new Dictionary, Func>(); + private readonly IList _registeredSingletons + = new List(); + private readonly Dictionary _singletonInstances + = new Dictionary(); + + private static readonly string CollectionDefaultKey = Guid.NewGuid().ToString(); + + #region Register + + /// + /// Register a type within the container. Useful when registering a type by key, so calls to Resolve(null, key) will work + /// + /// The type of class being registered + /// If specified, will associate a specific instance for this type + /// Indicates if the registration should yield a singleton object when resolved + /// The container, complete with new registration + public IMicroIocContainer Register(string key = null, bool isSingleton = false) + { + return Register(key, isSingleton); + } + + /// + /// Register an implementation type against an interface or class + /// + /// The type of interface or class to be registered + /// The type of concrete class to be instantiated when is resolved from the container. + /// The container, complete with new registration + public IMicroIocContainer Register(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(fromType, key)] = () => BuildFromType(toType); + return this; + } + + /// + /// Register a specific instance of a concrete implementation for an interface or class + /// + /// The type of interface or class to be registered + /// The instance to register in the container + /// (Optional) a key to specify the instance within the container + /// The container, complete with new registration + public IMicroIocContainer RegisterInstance(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, key)] = () => instance; + return this; + } + + #endregion + + #region Resolve + + /// + /// Resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// The registered instance if key is specified, or a dynamically instantiated instance, if not + public T Resolve(string key = null) + { + return (T) Resolve(typeof (T), key); + } + + /// + /// Try to resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// An instance of if registered, or null + public T TryResolve(string key) where T : class + { + return (T) TryResolve(typeof (T), key); + } + + /// + /// Resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// The registered instance if key is specified, or a dynamically instantiated instance, if not + public object Resolve(Type type, string key = null) + { + var result = ResolveCore(type, key); + BuildUp(result); + return result; + } + + /// + /// Try to resolve an instance of the specified interface (or class) Type + /// + /// The type of interface or class to be resolved + /// (Optional) a key to specify the instance within the container + /// An instance of if registered, or null + public object TryResolve(Type type, string key) + { + try + { + return Resolve(type, key); + } + catch + { + return null; + } + } + + /// + /// Resolve all registered instances of a specified type + /// + /// The type of interface or class to be resolved + /// A collection of registered instances. If no instances are registered, returns empty collection, not null + public IEnumerable ResolveAll() + { + var allObjects = ResolveAll(typeof (T)); + + return allObjects.Select(obj => (T) obj); + } + + /// + /// Resolve all registered instances of a specified type + /// + /// The type of interface or class to be resolved + /// A collection of registered instances. If no instances are registered, returns empty collection, not null + public IEnumerable ResolveAll(Type type) + { + return _resolverDictionary.Keys + .Where(key => key.Item1 == type) + .Select(t => _resolverDictionary[t]()); + } + + #endregion + + /// + /// Create an instance with properties from the container. + /// Only properties attributed [Inject] will be set. + /// + /// + 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, key)) + ? _resolverDictionary[new Tuple(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(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 + } +} \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Exceptions/ResolutionException.cs b/main/Libs/MicroIoc/MicroIoc.Core/Exceptions/ResolutionException.cs new file mode 100644 index 0000000..d06ce09 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Exceptions/ResolutionException.cs @@ -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) { } + } +} \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Extensions/ConfigurationExtensions.cs b/main/Libs/MicroIoc/MicroIoc.Core/Extensions/ConfigurationExtensions.cs new file mode 100644 index 0000000..4734122 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Extensions/ConfigurationExtensions.cs @@ -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(this IConfiguration configuration, Expression> 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(new InjectedProperty(propertyInfo.Name, value)); + } + + public static IConfiguration ConstructorParam(this IConfiguration configuration, string name, TParam value) + { + return configuration.Configure(new InjectedConstructorParam(name, value)); + } + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Extensions/PatternExtensions.cs b/main/Libs/MicroIoc/MicroIoc.Core/Extensions/PatternExtensions.cs new file mode 100644 index 0000000..416efdb --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Extensions/PatternExtensions.cs @@ -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; + } + } +} diff --git a/main/Libs/MicroIoc/MicroIoc.Core/MicroIoc.Core.csproj b/main/Libs/MicroIoc/MicroIoc.Core/MicroIoc.Core.csproj new file mode 100644 index 0000000..7e783ef --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/MicroIoc.Core.csproj @@ -0,0 +1,75 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {23F63AE9-A436-4B27-9113-4142C09ADD08} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + MicroIoc + MicroIoc + v4.0 + $(TargetFrameworkVersion) + WindowsPhone + Silverlight + false + true + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Properties/AssemblyInfo.cs b/main/Libs/MicroIoc/MicroIoc.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6a1f3c4 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Properties/AssemblyInfo.cs @@ -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")] diff --git a/main/Libs/MicroIoc/MicroIoc.Core/Tuple.cs b/main/Libs/MicroIoc/MicroIoc.Core/Tuple.cs new file mode 100644 index 0000000..87779e9 --- /dev/null +++ b/main/Libs/MicroIoc/MicroIoc.Core/Tuple.cs @@ -0,0 +1,52 @@ +namespace MicroIoc +{ + public class Tuple + { + 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 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)) + { + return false; + } + return Equals((Tuple)obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Item1.GetHashCode() * 397) ^ Item2.GetHashCode(); + } + } + } +} \ No newline at end of file diff --git a/main/MyFriendsAround.WP7/App.xaml.cs b/main/MyFriendsAround.WP7/App.xaml.cs index 5163e00..ff61a3e 100644 --- a/main/MyFriendsAround.WP7/App.xaml.cs +++ b/main/MyFriendsAround.WP7/App.xaml.cs @@ -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(); + locator.Cleanup(); } // Code to execute if a navigation fails diff --git a/main/MyFriendsAround.WP7/Helpers/Navigation/IPageNavigation.cs b/main/MyFriendsAround.WP7/Helpers/Navigation/IPageNavigation.cs new file mode 100644 index 0000000..f8b7fb7 --- /dev/null +++ b/main/MyFriendsAround.WP7/Helpers/Navigation/IPageNavigation.cs @@ -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(); + } +} diff --git a/main/MyFriendsAround.WP7/Helpers/Navigation/PageNavigation.cs b/main/MyFriendsAround.WP7/Helpers/Navigation/PageNavigation.cs new file mode 100644 index 0000000..353c1c3 --- /dev/null +++ b/main/MyFriendsAround.WP7/Helpers/Navigation/PageNavigation.cs @@ -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 + } +} diff --git a/main/MyFriendsAround.WP7/MyFriendsAround.WP7.csproj b/main/MyFriendsAround.WP7/MyFriendsAround.WP7.csproj index acc49da..59c6ecb 100644 --- a/main/MyFriendsAround.WP7/MyFriendsAround.WP7.csproj +++ b/main/MyFriendsAround.WP7/MyFriendsAround.WP7.csproj @@ -116,7 +116,12 @@ App.xaml - + + + + AboutPage.xaml + + MainPage.xaml @@ -126,8 +131,11 @@ + + + @@ -135,7 +143,11 @@ MSBuild:Compile Designer - + + Designer + MSBuild:Compile + + MSBuild:Compile Designer @@ -158,12 +170,11 @@ Always - PreserveNewest - - + + @@ -176,6 +187,10 @@ {A128812A-1249-4562-BDF4-5E17951B8434} GpsEmulatorClient + + {23F63AE9-A436-4B27-9113-4142C09ADD08} + MicroIoc.Core + {B55A0F90-2B5A-4C4B-88F4-013AA1629866} Phone7.Fx.Preview diff --git a/main/MyFriendsAround.WP7/Properties/WMAppManifest.xml b/main/MyFriendsAround.WP7/Properties/WMAppManifest.xml index 4a43b8c..d6ddf84 100644 --- a/main/MyFriendsAround.WP7/Properties/WMAppManifest.xml +++ b/main/MyFriendsAround.WP7/Properties/WMAppManifest.xml @@ -17,7 +17,7 @@ - + diff --git a/main/MyFriendsAround.WP7/README_FIRST.txt b/main/MyFriendsAround.WP7/README_FIRST.txt deleted file mode 100644 index 02b8f61..0000000 --- a/main/MyFriendsAround.WP7/README_FIRST.txt +++ /dev/null @@ -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. \ No newline at end of file diff --git a/main/MyFriendsAround.WP7/Utils/SerializationHelper.cs b/main/MyFriendsAround.WP7/Utils/SerializationHelper.cs index 6525be6..fcf7555 100644 --- a/main/MyFriendsAround.WP7/Utils/SerializationHelper.cs +++ b/main/MyFriendsAround.WP7/Utils/SerializationHelper.cs @@ -28,5 +28,6 @@ namespace MyFriendsAround.WP7.Utils { return JsonConvert.SerializeObject(obj); } + } } diff --git a/main/MyFriendsAround.WP7/ViewModel/AboutViewModel.cs b/main/MyFriendsAround.WP7/ViewModel/AboutViewModel.cs new file mode 100644 index 0000000..bc435ac --- /dev/null +++ b/main/MyFriendsAround.WP7/ViewModel/AboutViewModel.cs @@ -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"; + } + } + + + /// + /// Initializes a new instance of the MainViewModel class. + /// + 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"; } + } + + } +} \ No newline at end of file diff --git a/main/MyFriendsAround.WP7/ViewModel/Container.cs b/main/MyFriendsAround.WP7/ViewModel/Container.cs new file mode 100644 index 0000000..e89699f --- /dev/null +++ b/main/MyFriendsAround.WP7/ViewModel/Container.cs @@ -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(); + } + } +} diff --git a/main/MyFriendsAround.WP7/ViewModel/MainViewModel.cs b/main/MyFriendsAround.WP7/ViewModel/MainViewModel.cs index d2ca7ba..5329081 100644 --- a/main/MyFriendsAround.WP7/ViewModel/MainViewModel.cs +++ b/main/MyFriendsAround.WP7/ViewModel/MainViewModel.cs @@ -51,14 +51,6 @@ namespace MyFriendsAround.WP7.ViewModel } } - public string Welcome - { - get - { - return "Welcome to MVVM Light"; - } - } - /// /// Initializes a new instance of the MainViewModel class. /// @@ -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 { diff --git a/main/MyFriendsAround.WP7/ViewModel/ViewModelBase.cs b/main/MyFriendsAround.WP7/ViewModel/ViewModelBase.cs new file mode 100644 index 0000000..d04b85a --- /dev/null +++ b/main/MyFriendsAround.WP7/ViewModel/ViewModelBase.cs @@ -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"); + } + } + + /// + /// Gets PageNavigation from Container + /// + public IPageNavigation PageNav + { + get + { + IPageNavigation pageNav = + (IPageNavigation)Container.Instance.Resolve(typeof(PageNavigation), "PageNavigation"); + return pageNav; + } + } + } +} diff --git a/main/MyFriendsAround.WP7/ViewModel/ViewModelLocator.cs b/main/MyFriendsAround.WP7/ViewModel/ViewModelLocator.cs index df60273..132d4f0 100644 --- a/main/MyFriendsAround.WP7/ViewModel/ViewModelLocator.cs +++ b/main/MyFriendsAround.WP7/ViewModel/ViewModelLocator.cs @@ -14,6 +14,7 @@ DataContext="{Binding Source={x:Static vm:ViewModelLocatorTemplate.ViewModelNameStatic}}" */ +using MyFriendsAround.WP7.Helpers.Navigation; namespace MyFriendsAround.WP7.ViewModel { /// @@ -55,81 +56,79 @@ namespace MyFriendsAround.WP7.ViewModel /// public class ViewModelLocator { - private static MainViewModel _main; /// /// Initializes a new instance of the ViewModelLocator class. /// public ViewModelLocator() { - ////if (ViewModelBase.IsInDesignModeStatic) - ////{ - //// // Create design time view models - ////} - ////else - ////{ - //// // Create run time view models - ////} - - CreateMain(); - } - - /// - /// Gets the Main property. - /// - 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"); } /// /// Gets the Main property. /// - [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(); + return mainViewModel; } } /// - /// Provides a deterministic way to delete the Main property. + /// Gets the About property. /// - public static void ClearMain() + public AboutViewModel About { - _main.Cleanup(); - _main = null; - } - - /// - /// Provides a deterministic way to create the Main property. - /// - public static void CreateMain() - { - if (_main == null) + get { - _main = new MainViewModel(); + AboutViewModel aboutViewModel = GetViewModel(); + return aboutViewModel; } } + /// /// Cleans up all the resources. /// - public static void Cleanup() + public void Cleanup() { - ClearMain(); + MainViewModel mainViewModel = GetViewModel(); + mainViewModel.Cleanup(); + AboutViewModel aboutViewModel = GetViewModel(); + aboutViewModel.Cleanup(); } + + + + #region Local Helpers + + private T GetViewModel() where T : ViewModelBase + { + // Create a new view model + T vm = Container.Instance.Resolve(); + + //Assign the Context from PageNavigation to Context property of the ViewModelBase + vm.Context = vm.PageNav.CurrentContext; + + return vm; + } + + #endregion } } \ No newline at end of file diff --git a/main/MyFriendsAround.WP7/Views/AboutPage.xaml b/main/MyFriendsAround.WP7/Views/AboutPage.xaml new file mode 100644 index 0000000..106895a --- /dev/null +++ b/main/MyFriendsAround.WP7/Views/AboutPage.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/main/MyFriendsAround.WP7/Views/AboutPage.xaml.cs b/main/MyFriendsAround.WP7/Views/AboutPage.xaml.cs new file mode 100644 index 0000000..1d5c596 --- /dev/null +++ b/main/MyFriendsAround.WP7/Views/AboutPage.xaml.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/main/MyFriendsAround.WP7/MainPage.xaml b/main/MyFriendsAround.WP7/Views/MainPage.xaml similarity index 95% rename from main/MyFriendsAround.WP7/MainPage.xaml rename to main/MyFriendsAround.WP7/Views/MainPage.xaml index e5778b1..7856dc7 100644 --- a/main/MyFriendsAround.WP7/MainPage.xaml +++ b/main/MyFriendsAround.WP7/Views/MainPage.xaml @@ -53,11 +53,6 @@ Grid.Row="1" Margin="0,0,0,70"> -