diff --git a/src/Artemis.UI/App.config b/src/Artemis.UI/App.config index 731f6de6c..cef76b5d2 100644 --- a/src/Artemis.UI/App.config +++ b/src/Artemis.UI/App.config @@ -1,6 +1,14 @@ - + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/App.xaml b/src/Artemis.UI/App.xaml index 7110a4142..ae032a192 100644 --- a/src/Artemis.UI/App.xaml +++ b/src/Artemis.UI/App.xaml @@ -1,12 +1,18 @@  + xmlns:s="https://github.com/canton7/Stylet" + xmlns:local="clr-namespace:Artemis.UI"> - + + + + + + diff --git a/src/Artemis.UI/App.xaml.cs b/src/Artemis.UI/App.xaml.cs index 148bf9ad3..cae2554ea 100644 --- a/src/Artemis.UI/App.xaml.cs +++ b/src/Artemis.UI/App.xaml.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; namespace Artemis.UI { /// - /// Interaction logic for App.xaml + /// Interaction logic for App.xaml /// public partial class App : Application { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/AppBootstrapper.cs b/src/Artemis.UI/AppBootstrapper.cs deleted file mode 100644 index ed60cb899..000000000 --- a/src/Artemis.UI/AppBootstrapper.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Linq; -using Artemis.UI.Ninject; -using Artemis.UI.ViewModels; -using Ninject; -using ReactiveUI; -using ReactiveUI.Fody.Helpers; -using Splat; - -namespace Artemis.UI -{ - public class AppBootstrapper : ReactiveObject, IScreen - { - public AppBootstrapper() - { - Router = new RoutingState(); - Kernel = new StandardKernel(new ViewsModule()); - - // Configure the Ninject kernel and set it up as the default for ReactiveUI - SetupNinject(Kernel); - - // Update the title on view change - this.WhenAnyValue(x => x.Router.CurrentViewModel) - .Subscribe(o => o.Subscribe(vm => { ViewTitle = vm != null ? vm.UrlPathSegment : ""; })); - - // Setup the sidebar that lives throughout the app - SidebarViewModel = Kernel.Get(); - // Navigate to the opening page of the application - Router.Navigate.Execute(Kernel.Get()); - } - - public IKernel Kernel { get; set; } - public ISidebarViewModel SidebarViewModel { get; } - public RoutingState Router { get; } - - [Reactive] - public string ViewTitle { get; set; } - - private void SetupNinject(IKernel kernel) - { - // Bind the main screen to IScreen - kernel.Bind().ToConstant(this); - - // Set up NInject to do DI - var customResolver = new FuncDependencyResolver( - (service, contract) => - { - if (contract != null) return kernel.GetAll(service, contract); - var items = kernel.GetAll(service); - var list = items.ToList(); - return list; - }, - (factory, service, contract) => - { - var binding = kernel.Bind(service).ToMethod(_ => factory()); - if (contract != null) binding.Named(contract); - }); - Locator.Current = customResolver; - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 78534aebb..f8a73ff1e 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -36,6 +36,9 @@ 4 + + ..\packages\Castle.Core.4.2.0\lib\net45\Castle.Core.dll + ..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll @@ -51,33 +54,22 @@ ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll - - ..\packages\reactiveui-core.7.4.0\lib\Net45\ReactiveUI.dll + + ..\packages\Ninject.Extensions.Conventions.3.3.0\lib\net45\Ninject.Extensions.Conventions.dll - - ..\packages\ReactiveUI.Fody.2.2.11\lib\net45\ReactiveUI.Fody.Helpers.dll + + ..\packages\Ninject.Extensions.Factory.3.3.2\lib\net45\Ninject.Extensions.Factory.dll - - ..\packages\Splat.1.6.0\lib\Net45\Splat.dll + + ..\packages\PropertyChanged.Fody.2.2.4.0\lib\net452\PropertyChanged.dll + + + ..\packages\Stylet.1.1.21\lib\net45\Stylet.dll + - - ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll - - - ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll - - - ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll - - - ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll - - - ..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll - ..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll @@ -99,34 +91,21 @@ MSBuild:Compile Designer - - + + + - - - - MainView.xaml - - - SidebarView.xaml - - - MSBuild:Compile - Designer - + + App.xaml Code - - MainWindow.xaml - Code - - + Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -178,14 +157,14 @@ - + - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs new file mode 100644 index 000000000..2495ca0d9 --- /dev/null +++ b/src/Artemis.UI/Bootstrapper.cs @@ -0,0 +1,16 @@ +using Artemis.UI.Ninject; +using Artemis.UI.Stylet; +using Artemis.UI.ViewModels; +using Ninject; + +namespace Artemis.UI +{ + public class Bootstrapper : NinjectBootstrapper + { + protected override void ConfigureIoC(IKernel kernel) + { + kernel.Load(); + base.ConfigureIoC(kernel); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/FodyWeavers.xml b/src/Artemis.UI/FodyWeavers.xml index e36b845f9..300d3fb14 100644 --- a/src/Artemis.UI/FodyWeavers.xml +++ b/src/Artemis.UI/FodyWeavers.xml @@ -1,4 +1,5 @@ - + + - + \ No newline at end of file diff --git a/src/Artemis.UI/MainWindow.xaml.cs b/src/Artemis.UI/MainWindow.xaml.cs deleted file mode 100644 index 3c92f393a..000000000 --- a/src/Artemis.UI/MainWindow.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MahApps.Metro.Controls; - -namespace Artemis.UI -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : MetroWindow - { - public MainWindow() - { - InitializeComponent(); - - AppBootstrapper = new AppBootstrapper(); - DataContext = AppBootstrapper; - } - - public AppBootstrapper AppBootstrapper { get; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs new file mode 100644 index 000000000..5b33287d3 --- /dev/null +++ b/src/Artemis.UI/Ninject/UiModule.cs @@ -0,0 +1,18 @@ +using Artemis.UI.ViewModels.Interfaces; +using Ninject.Extensions.Conventions; +using Ninject.Modules; + +namespace Artemis.UI.Ninject +{ + public class UIModule : NinjectModule + { + public override void Load() + { + // Bind all viewmodels + Kernel.Bind(x => + { + x.FromThisAssembly().SelectAllClasses().InheritedFrom().BindAllInterfaces(); + }); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/ViewsModule.cs b/src/Artemis.UI/Ninject/ViewsModule.cs deleted file mode 100644 index 59af3febf..000000000 --- a/src/Artemis.UI/Ninject/ViewsModule.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Artemis.UI.ViewModels; -using Ninject.Modules; - -namespace Artemis.UI.Ninject -{ - public class ViewsModule : NinjectModule - { - public override void Load() - { - Bind().To(); - Bind().To().InSingletonScope(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Properties/AssemblyInfo.cs b/src/Artemis.UI/Properties/AssemblyInfo.cs index 6c3cfcaa8..f3e678ec6 100644 --- a/src/Artemis.UI/Properties/AssemblyInfo.cs +++ b/src/Artemis.UI/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Windows; @@ -33,11 +31,11 @@ using System.Windows; [assembly: ThemeInfo( ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) + //(used if a resource is not found in the page, + // or application resource dictionaries) ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) )] @@ -52,4 +50,4 @@ using System.Windows; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/src/Artemis.UI/Properties/Settings.settings b/src/Artemis.UI/Properties/Settings.settings index 033d7a5e9..c14891b94 100644 --- a/src/Artemis.UI/Properties/Settings.settings +++ b/src/Artemis.UI/Properties/Settings.settings @@ -1,4 +1,5 @@  + diff --git a/src/Artemis.UI/Stylet/NinjectBootstrapper.cs b/src/Artemis.UI/Stylet/NinjectBootstrapper.cs new file mode 100644 index 000000000..9d83df960 --- /dev/null +++ b/src/Artemis.UI/Stylet/NinjectBootstrapper.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Ninject; +using Stylet; + +namespace Artemis.UI.Stylet +{ + public class NinjectBootstrapper : BootstrapperBase where TRootViewModel : class + { + private object _rootViewModel; + private IKernel kernel; + + protected virtual object RootViewModel => + _rootViewModel ?? (_rootViewModel = GetInstance(typeof(TRootViewModel))); + + protected override void ConfigureBootstrapper() + { + kernel = new StandardKernel(); + DefaultConfigureIoC(kernel); + ConfigureIoC(kernel); + } + + /// + /// Carries out default configuration of the IoC container. Override if you don't want to do this + /// + protected virtual void DefaultConfigureIoC(IKernel kernel) + { + var viewManagerConfig = new ViewManagerConfig + { + ViewFactory = GetInstance, + ViewAssemblies = new List {GetType().Assembly} + }; + kernel.Bind().ToConstant(new ViewManager(viewManagerConfig)); + + kernel.Bind().ToConstant(this).InTransientScope(); + kernel.Bind().ToMethod(c => new WindowManager(c.Kernel.Get(), + () => c.Kernel.Get(), c.Kernel.Get())).InSingletonScope(); + kernel.Bind().To().InSingletonScope(); + kernel.Bind().To(); // Not singleton! + } + + /// + /// Override to add your own types to the IoC container. + /// + protected virtual void ConfigureIoC(IKernel kernel) + { + } + + public override object GetInstance(Type type) + { + return kernel.Get(type); + } + + protected override void Launch() + { + DisplayRootView(RootViewModel); + } + + public override void Dispose() + { + base.Dispose(); + ScreenExtensions.TryDispose(_rootViewModel); + if (kernel != null) + kernel.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/HomeViewModel.cs b/src/Artemis.UI/ViewModels/HomeViewModel.cs new file mode 100644 index 000000000..b671bd422 --- /dev/null +++ b/src/Artemis.UI/ViewModels/HomeViewModel.cs @@ -0,0 +1,23 @@ +using System; +using System.Diagnostics; +using Artemis.UI.ViewModels.Interfaces; +using Stylet; + +namespace Artemis.UI.ViewModels +{ + public class HomeViewModel : Screen, IMainViewModel + { + public string Title => "Home"; + + public void OpenUrl(string url) + { + // Don't open anything but valid URIs + if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) + Process.Start(url); + } + } + + public interface IMainViewModel : IArtemisViewModel + { + } +} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/Interfaces/IArtemisViewModel.cs b/src/Artemis.UI/ViewModels/Interfaces/IArtemisViewModel.cs index 532031971..fae827f1c 100644 --- a/src/Artemis.UI/ViewModels/Interfaces/IArtemisViewModel.cs +++ b/src/Artemis.UI/ViewModels/Interfaces/IArtemisViewModel.cs @@ -1,10 +1,7 @@ -using ReactiveUI; - -namespace Artemis.UI.ViewModels.Interfaces +namespace Artemis.UI.ViewModels.Interfaces { - public interface IArtemisViewModel : IRoutableViewModel + public interface IArtemisViewModel { string Title { get; } - string Icon { get; } } } \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/MainViewModel.cs b/src/Artemis.UI/ViewModels/MainViewModel.cs deleted file mode 100644 index 9e093f676..000000000 --- a/src/Artemis.UI/ViewModels/MainViewModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Diagnostics; -using System.Threading.Tasks; -using Artemis.UI.ViewModels.Interfaces; -using ReactiveUI; - -namespace Artemis.UI.ViewModels -{ - public class MainViewModel : ReactiveObject, IMainViewModel - { - public MainViewModel(IScreen screen, ISidebarViewModel sidebarViewModel) - { - HostScreen = screen; - OpenUrl = ReactiveCommand.CreateFromTask(OpenUrlAsync); - - // Add this view as a menu item - sidebarViewModel.MenuItems.Add(this); - } - - public IScreen HostScreen { get; } - public string UrlPathSegment => Title.ToLower(); - public string Title => "Home"; - public string Icon => "Home"; - - public ReactiveCommand OpenUrl { get; } - - private async Task OpenUrlAsync(string url) - { - await Task.Run(() => Process.Start(url)); - } - } - - public interface IMainViewModel : IArtemisViewModel - { - ReactiveCommand OpenUrl { get; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/RootViewModel.cs b/src/Artemis.UI/ViewModels/RootViewModel.cs new file mode 100644 index 000000000..ae1022526 --- /dev/null +++ b/src/Artemis.UI/ViewModels/RootViewModel.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using Artemis.UI.ViewModels.Interfaces; +using Stylet; + +namespace Artemis.UI.ViewModels +{ + public class RootViewModel : Conductor.Collection.OneActive + { + public RootViewModel(ICollection artemisViewModels) + { + // Add the built-in items + Items.AddRange(artemisViewModels); + // Activate the home item + ActiveItem = artemisViewModels.First(v => v.GetType() == typeof(HomeViewModel)); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/SidebarViewModel.cs b/src/Artemis.UI/ViewModels/SidebarViewModel.cs deleted file mode 100644 index 58aa6cbb7..000000000 --- a/src/Artemis.UI/ViewModels/SidebarViewModel.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.ObjectModel; -using Artemis.UI.ViewModels.Interfaces; -using ReactiveUI; - -namespace Artemis.UI.ViewModels -{ - public class SidebarViewModel : ReactiveObject, ISidebarViewModel - { - public SidebarViewModel(IScreen screen) - { - HostScreen = screen; - MenuItems = new ObservableCollection(); - } - - public IScreen HostScreen { get; } - public ObservableCollection MenuItems { get; set; } - } - - public interface ISidebarViewModel - { - ObservableCollection MenuItems { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Views/MainView.xaml b/src/Artemis.UI/Views/HomeView.xaml similarity index 67% rename from src/Artemis.UI/Views/MainView.xaml rename to src/Artemis.UI/Views/HomeView.xaml index db216f5fe..1e298826b 100644 --- a/src/Artemis.UI/Views/MainView.xaml +++ b/src/Artemis.UI/Views/HomeView.xaml @@ -1,23 +1,27 @@ - + mc:Ignorable="d" + d:DesignHeight="574.026" + d:DesignWidth="1029.87" + d:DataContext="{d:DesignInstance vms:HomeViewModel, IsDesignTimeCreatable=True}"> - - - + + + - + @@ -59,42 +63,57 @@ - + Have a chat - + + + + - + - - - - - + + + + @@ -145,15 +177,15 @@ Margin="32" Grid.Row="1"> --> - + \ No newline at end of file diff --git a/src/Artemis.UI/Views/MainView.xaml.cs b/src/Artemis.UI/Views/MainView.xaml.cs deleted file mode 100644 index e85f0f599..000000000 --- a/src/Artemis.UI/Views/MainView.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using Artemis.UI.ViewModels; -using ReactiveUI; - -namespace Artemis.UI.Views -{ - /// - /// Interaction logic for MainView.xaml - /// - public partial class MainView : UserControl, IViewFor - { - public static readonly DependencyProperty ViewModelProperty = - DependencyProperty.Register("ViewModel", typeof(IMainViewModel), typeof(MainView), new PropertyMetadata(null)); - - public MainView() - { - InitializeComponent(); - this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext); - } - - object IViewFor.ViewModel - { - get => ViewModel; - set => ViewModel = (IMainViewModel) value; - } - - public IMainViewModel ViewModel { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/MainWindow.xaml b/src/Artemis.UI/Views/RootView.xaml similarity index 81% rename from src/Artemis.UI/MainWindow.xaml rename to src/Artemis.UI/Views/RootView.xaml index a80ee238e..bc1ab4a6e 100644 --- a/src/Artemis.UI/MainWindow.xaml +++ b/src/Artemis.UI/Views/RootView.xaml @@ -1,18 +1,19 @@ - + d:DesignWidth="1113.251" + d:DataContext="{d:DesignInstance vms:RootViewModel}"> @@ -71,33 +72,42 @@ - + + + - + - -