1
0
mirror of https://github.com/DarthAffe/Arge.git synced 2022-11-28 19:26:16 +00:00

Moved away from Caliburn and Added some basic stuff with ReactiveUI

(I'm not quite happy with everything so far, but it seems like I'm to stupid to understand how to correctly use routing with the layout I want)
This commit is contained in:
Darth Affe 2017-05-25 20:50:00 +02:00
parent a9f7cbd61c
commit 2576ff2ca2
29 changed files with 464 additions and 282 deletions

View File

@ -1,14 +1,10 @@
<Application x:Class="Arge.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:bootstrapper="clr-namespace:Arge.Bootstrapper"
xmlns:resources="clr-namespace:Arge.Resources">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<bootstrapper:ArgeBootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
<resources:CachedResourceDictionary Source="/Arge;component/Resources/Arge.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@ -1,7 +1,41 @@
using System.Windows;
using Arge.Bootstrapper;
namespace Arge
{
public partial class App : Application
{ }
{
#region Properties & Fields
private readonly ArgeBootstrapper _bootstrapper;
#endregion
#region Constructors
public App()
{
_bootstrapper = new ArgeBootstrapper();
}
#endregion
#region Methods
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
_bootstrapper.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
_bootstrapper.OnExit(e);
}
#endregion
}
}

View File

@ -36,15 +36,6 @@
<ApplicationIcon>Resources\ArgeBee.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Caliburn.Micro, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.Core.3.0.3\lib\net45\Caliburn.Micro.dll</HintPath>
</Reference>
<Reference Include="Caliburn.Micro.Platform, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.dll</HintPath>
</Reference>
<Reference Include="Caliburn.Micro.Platform.Core, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
@ -57,18 +48,38 @@
<Reference Include="Microsoft.Practices.Unity.RegistrationByConvention, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f, processorArchitecture=MSIL">
<HintPath>..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI, Version=7.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\reactiveui-core.7.3.0\lib\Net45\ReactiveUI.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI.Events, Version=7.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\reactiveui-events.7.3.0\lib\Net45\ReactiveUI.Events.dll</HintPath>
</Reference>
<Reference Include="RGB.NET.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll</HintPath>
</Reference>
<Reference Include="Splat, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.1.4.0\lib\Net45\Splat.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\System.Windows.Interactivity.dll</HintPath>
<Private>True</Private>
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Windows.Threading, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
@ -92,21 +103,26 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Attributes\FileNameAttribute.cs" />
<Compile Include="Bootstrapper\ArgeWindowManager.cs" />
<Compile Include="Bootstrapper\NavigationManager.cs" />
<Compile Include="Bootstrapper\UnityBootstrapper.cs" />
<Compile Include="Bootstrapper\UnityDependencyResolver.cs" />
<Compile Include="Configuration\Config.cs" />
<Compile Include="Configuration\ConfigEntryType.cs" />
<Compile Include="Controls\BlurredDecorationWindow.cs" />
<Compile Include="Controls\ImageButton.cs" />
<Compile Include="Controls\Window\BlurredDecorationWindow.cs" />
<Compile Include="Controls\Buttons\ImageButton.cs" />
<Compile Include="Enums\NavigationTargets.cs" />
<Compile Include="Extensions\EnumExtension.cs" />
<Compile Include="Misc\ActionCommand.cs" />
<Compile Include="Misc\BindingProxy.cs" />
<Compile Include="Resources\CachedResourceDictionary.cs" />
<Compile Include="Resources\ImageSources.cs" />
<Compile Include="Themes\Theme.cs" />
<Compile Include="Themes\ThemeManager.cs" />
<Compile Include="Misc\AbstractBindable.cs" />
<Compile Include="ViewModels\AbstractViewModel.cs" />
<Compile Include="ViewModels\NavigationViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="Views\AbstractView.cs" />
<Compile Include="Views\NavigationView.xaml.cs">
<DependentUpon>NavigationView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ShellView.xaml.cs">
<DependentUpon>ShellView.xaml</DependentUpon>
</Compile>
@ -141,7 +157,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="AttachedProperties\" />
<Folder Include="Enums\" />
</ItemGroup>
<ItemGroup>
<Page Include="Converter\Converter.xaml">
@ -172,6 +187,10 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Page Include="Views\NavigationView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ShellView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=views_005Cbase/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,10 +1,14 @@
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media.Imaging;
using Arge.Configuration;
using Arge.Controls.Window;
using Arge.Themes;
using Arge.ViewModels;
using Caliburn.Micro;
using Arge.Views;
using Microsoft.Practices.Unity;
using ReactiveUI;
namespace Arge.Bootstrapper
{
@ -14,23 +18,40 @@ namespace Arge.Bootstrapper
protected override void RegisterTypes()
{
RegisterInterface<IWindowManager, ArgeWindowManager>();
RegisterServices();
RegisterViews();
}
private void RegisterServices()
{
RegisterSingleton<ThemeManager>();
}
protected override void OnStartup(object sender, StartupEventArgs e)
private void RegisterViews()
{
RegisterView<ShellView, ShellViewModel>();
RegisterView<NavigationView, NavigationViewModel>();
}
protected override void InitializeHandlers()
{
}
protected override void Start()
{
Config.Instance.Load();
Container.Resolve<ThemeManager>().LoadTheme(Config.Instance[ConfigEntryType.Theme]);
Dictionary<string, object> settings = new Dictionary<string, object>
{
{ "Title", "Arge" },
{ "Width" , 1280 },
{ "Height" , 720 }
};
DisplayRootViewFor<ShellViewModel>(settings);
BlurredDecorationWindow window = new BlurredDecorationWindow
{
Width = 1280,
Height = 720,
Icon = new BitmapImage(new Uri("pack://application:,,,/Arge;component/Resources/ArgeBee.ico")),
IconCommand = ReactiveCommand.Create(() => Process.Start("http://arge.be")),
Content = Container.Resolve<ShellView>()
};
Application.Current.MainWindow = window;
window.Show();
}
#endregion

View File

@ -1,48 +0,0 @@
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media.Imaging;
using Arge.Controls;
using Arge.Misc;
using Caliburn.Micro;
namespace Arge.Bootstrapper
{
public class ArgeWindowManager : WindowManager
{
#region Methods
protected override Window EnsureWindow(object model, object view, bool isDialog)
{
Window window = view as Window;
if (window == null)
{
window = new BlurredDecorationWindow()
{
Content = view,
SizeToContent = SizeToContent.Manual,
Icon = new BitmapImage(new Uri("pack://application:,,,/Arge;component/Resources/ArgeBee.ico")),
IconCommand = new ActionCommand(() => Process.Start("http://arge.be"))
};
window.SetValue(View.IsGeneratedProperty, true);
Window owner = InferOwnerOf(window);
if (owner != null)
{
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
window.Owner = owner;
}
else
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
else
{
Window owner = InferOwnerOf(window);
if ((owner != null) && isDialog)
window.Owner = owner;
}
return window;
}
#endregion
}
}

View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using Arge.Enums;
using Microsoft.Practices.Unity;
namespace Arge.Bootstrapper
{
//TODO DarthAffe 21.05.2017: This allows some sort of fake VM-first - One day I should make this cleaner ...
public class NavigationManager
{
#region Properties & Fields
public static NavigationManager Instance { get; private set; }
private readonly Dictionary<Type, Type> _viewTypeMapping = new Dictionary<Type, Type>();
private readonly IUnityContainer _container;
public object Navigation { get; private set; }
public object Layers { get; private set; }
public object Selection { get; private set; }
public object Action { get; private set; }
public object Surface { get; private set; }
#endregion
#region Constructors
private NavigationManager(IUnityContainer container)
{
this._container = container;
}
#endregion
#region Methods
public static void Initialize(IUnityContainer container)
{
Instance = new NavigationManager(container);
}
public void RegisterViewTypes(Type viewType, Type viewModelType)
{
_viewTypeMapping[viewModelType] = viewType;
}
public void Navigate<TTarget>(NavigationTargets target)
{
Navigate(target, typeof(TTarget));
}
public void Navigate(NavigationTargets target, Type targetType)
{
Type viewType;
if (!_viewTypeMapping.TryGetValue(targetType, out viewType))
viewType = targetType;
Navigate(target, _container.Resolve(viewType));
}
public void Navigate(NavigationTargets target, object view)
{
switch (target)
{
case NavigationTargets.Navigation:
Navigation = view;
break;
case NavigationTargets.Layers:
Layers = view;
break;
case NavigationTargets.Selection:
Selection = view;
break;
case NavigationTargets.Action:
Action = view;
break;
case NavigationTargets.Surface:
Surface = view;
break;
}
}
#endregion
}
}

View File

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using Caliburn.Micro;
using System.Windows;
using Microsoft.Practices.Unity;
using ReactiveUI;
using Splat;
namespace Arge.Bootstrapper
{
public abstract class UnityBootstrapper : BootstrapperBase
public abstract class UnityBootstrapper
{
#region Properties & Fields
@ -13,47 +14,38 @@ namespace Arge.Bootstrapper
#endregion
#region Constructors
protected UnityBootstrapper()
{
Initialize();
}
#endregion
#region Methods
protected override void Configure()
public virtual void OnStartup(StartupEventArgs e)
{
Configure();
RegisterTypes();
InitializeHandlers();
Start();
}
public virtual void OnExit(ExitEventArgs e)
{
}
protected virtual void Configure()
{
Container = new UnityContainer();
RegisterSingleton(Container);
RegisterInterface<IEventAggregator, EventAggregator>();
RegisterTypes();
Locator.Current = new UnityDependencyResolver(Container);
NavigationManager.Initialize(Container);
}
protected abstract void RegisterTypes();
protected override object GetInstance(Type service, string key)
{
return key != null ? Container.Resolve(service, key) : Container.Resolve(service);
}
protected abstract void InitializeHandlers();
protected override IEnumerable<object> GetAllInstances(Type service)
{
return Container.ResolveAll(service);
}
protected override void BuildUp(object instance)
{
instance = Container.BuildUp(instance);
base.BuildUp(instance);
}
protected abstract void Start();
#region Container-Registration
protected void RegisterInterface<TInterface, TImplementation>(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null)
protected void RegisterService<TInterface, TImplementation>(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null)
where TImplementation : TInterface
{
RegisterTypeIfMissing(typeof(TInterface), typeof(TImplementation), registerAsSingleton, uniqueName);
@ -61,6 +53,16 @@ namespace Arge.Bootstrapper
RegisterTypeIfMissing(typeof(TImplementation), typeof(TImplementation), registerAsSingleton, uniqueName);
}
protected void RegisterView<TView, TViewModel>()
where TView : IViewFor<TViewModel>
where TViewModel : class, IReactiveObject
{
RegisterTypeIfMissing(typeof(TView), typeof(TView), false);
RegisterTypeIfMissing(typeof(TViewModel), typeof(TViewModel), false);
NavigationManager.Instance.RegisterViewTypes(typeof(TView), typeof(TViewModel));
}
protected void RegisterSingleton<T>()
{
RegisterTypeIfMissing(typeof(T), typeof(T), true);

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Splat;
namespace Arge.Bootstrapper
{
//HACK DarthAffe 21.05.2017: I've no idea if this a good implementation - don't think so but it seems to work ...
public class UnityDependencyResolver : IMutableDependencyResolver
{
#region Properties & Fields
private readonly IUnityContainer _container;
private int _defaultCounter = 0;
#endregion
#region Constructors
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
#endregion
#region Methods
public void Dispose() { }
public object GetService(Type serviceType, string contract = null)
{
return _container.Resolve(serviceType, contract ?? "default");
}
public IEnumerable<object> GetServices(Type serviceType, string contract = null)
{
return _container.ResolveAll(serviceType);
}
public void Register(Func<object> factory, Type serviceType, string contract = null)
{
if (_container.IsRegistered(serviceType, contract ?? "default"))
contract = $"{(contract ?? "default")}_{_defaultCounter++}";
_container.RegisterType(serviceType, serviceType, contract ?? "default", new InjectionFactory(c => factory()));
}
public IDisposable ServiceRegistrationCallback(Type serviceType, string contract, Action<IDisposable> callback)
{
throw new NotSupportedException();
}
#endregion
}
}

View File

@ -2,7 +2,7 @@
using System.Windows.Controls;
using System.Windows.Media;
namespace Arge.Controls
namespace Arge.Controls.Buttons
{
public class ImageButton : Button
{

View File

@ -3,14 +3,14 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Arge.Controls
namespace Arge.Controls.Window
{
[TemplatePart(Name = "PART_Decoration", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "PART_Content", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "PART_CloseButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_MinimizeButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_IconButton", Type = typeof(Button))]
public class BlurredDecorationWindow : Window
public class BlurredDecorationWindow : System.Windows.Window
{
#region DependencyProperties
// ReSharper disable InconsistentNaming

View File

@ -0,0 +1,11 @@
namespace Arge.Enums
{
public enum NavigationTargets
{
Navigation,
Layers,
Selection,
Action,
Surface
}
}

View File

@ -1,44 +0,0 @@
using System.Runtime.CompilerServices;
using Caliburn.Micro;
namespace Arge.Misc
{
public abstract class AbstractBindable : PropertyChangedBase
{
#region Method
/// <summary>
/// Checks if the property already matches the desirec value or needs to be updated.
/// </summary>
/// <typeparam name="T">Type of the property.</typeparam>
/// <param name="storage">Reference to the backing-filed.</param>
/// <param name="value">Value to apply.</param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool RequiresUpdate<T>(ref T storage, T value)
{
return !Equals(storage, value);
}
/// <summary>
/// Checks if the property already matches the desired value and updates it if not.
/// </summary>
/// <typeparam name="T">Type of the property.</typeparam>
/// <param name="storage">Reference to the backing-filed.</param>
/// <param name="value">Value to apply.</param>
/// <param name="propertyName">Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param>
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (!RequiresUpdate(ref storage, value)) return false;
storage = value;
// ReSharper disable once ExplicitCallerInfoArgument
NotifyOfPropertyChange(propertyName);
return true;
}
#endregion
}
}

View File

@ -1,50 +0,0 @@
using System;
using System.Windows.Input;
namespace Arge.Misc
{
public class ActionCommand : ICommand
{
#region Properties & Fields
private readonly Func<bool> _canExecute;
private readonly Action _command;
#endregion
#region Constructors
public ActionCommand(Action command, Func<bool> canExecute = null)
{
this._command = command;
this._canExecute = canExecute;
}
#endregion
#region Methods
public bool CanExecute(object parameter)
{
return _canExecute?.Invoke() ?? true;
}
public void Execute(object parameter)
{
_command?.Invoke();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, new EventArgs());
}
#endregion
#region Events
public event EventHandler CanExecuteChanged;
#endregion
}
}

View File

@ -1,28 +0,0 @@
using System.Windows;
namespace Arge.Misc
{
public class BindingProxy : Freezable
{
#region Properties & Fields
// ReSharper disable InconsistentNaming
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
"Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
public object Data
{
get => GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
// ReSharper restore InconsistentNaming
#endregion
#region Methods
protected override Freezable CreateInstanceCore() => new BindingProxy();
#endregion
}
}

View File

@ -1,7 +1,8 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resources="clr-namespace:Arge.Resources"
xmlns:controls="clr-namespace:Arge.Controls">
xmlns:buttons="clr-namespace:Arge.Controls.Buttons"
xmlns:window="clr-namespace:Arge.Controls.Window">
<resources:CachedResourceDictionary.MergedDictionaries>
<resources:CachedResourceDictionary Source="/Arge;component/Styles/BlurredDecorationWindow.xaml" />
@ -9,8 +10,8 @@
<resources:CachedResourceDictionary Source="/Arge;component/Styles/ToolTip.xaml" />
</resources:CachedResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type controls:BlurredDecorationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" />
<Style TargetType="{x:Type controls:ImageButton}" BasedOn="{StaticResource StyleImageButton}" />
<Style TargetType="{x:Type window:BlurredDecorationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" />
<Style TargetType="{x:Type buttons:ImageButton}" BasedOn="{StaticResource StyleImageButton}" />
<Style TargetType="ToolTip" BasedOn="{StaticResource StyleToolTip}" />
</resources:CachedResourceDictionary>

View File

@ -4,11 +4,11 @@ using System.Linq;
using System.Reflection;
using System.Windows.Media;
using Arge.Attributes;
using Arge.Misc;
using ReactiveUI;
namespace Arge.Resources
{
public class ImageSources : AbstractBindable
public class ImageSources : ReactiveObject
{
#region Properties & Fields
@ -47,7 +47,8 @@ namespace Arge.Resources
if (string.IsNullOrWhiteSpace(fileName)) continue;
propertyInfo.SetValue(this, ConvertToImageSource(files.FirstOrDefault(x => string.Equals(Path.GetFileNameWithoutExtension(x), fileName, StringComparison.OrdinalIgnoreCase))));
NotifyOfPropertyChange(propertyInfo.Name);
// ReSharper disable once ExplicitCallerInfoArgument - impossible!
this.RaisePropertyChanged(propertyInfo.Name);
}
}

View File

@ -1,7 +1,8 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Arge.Controls"
xmlns:resources="clr-namespace:Arge.Resources">
xmlns:resources="clr-namespace:Arge.Resources"
xmlns:buttons="clr-namespace:Arge.Controls.Buttons"
xmlns:window="clr-namespace:Arge.Controls.Window">
<resources:CachedResourceDictionary.MergedDictionaries>
<resources:CachedResourceDictionary Source="/Arge;component/Styles/ImageButton.xaml" />
@ -10,7 +11,7 @@
<Style x:Key="StyleImageButtonWindow"
BasedOn="{StaticResource StyleImageButtonWithOpacity}"
TargetType="{x:Type controls:ImageButton}">
TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Padding" Value="4" />
<Setter Property="Margin" Value="4" />
<Setter Property="VerticalAlignment" Value="Top" />
@ -19,7 +20,7 @@
</Style>
<Style x:Key="StyleBlurredDecorationWindow"
TargetType="{x:Type controls:BlurredDecorationWindow}">
TargetType="{x:Type window:BlurredDecorationWindow}">
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanResize" />
<Setter Property="AllowsTransparency" Value="True" />
@ -30,7 +31,6 @@
<Setter Property="BorderBrush" Value="{DynamicResource BrushWindowBorder}" />
<Setter Property="Background" Value="{DynamicResource BrushWindowBackground}" />
<Setter Property="BackgroundImage" Value="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowBackground}" />
<Setter Property="ToolTip" Value="http://arge.be" />
<Setter Property="MinWidth" Value="256" />
<Setter Property="MinHeight" Value="144" />
<Setter Property="SnapsToDevicePixels" Value="True" />
@ -43,7 +43,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:BlurredDecorationWindow}">
<ControlTemplate TargetType="{x:Type window:BlurredDecorationWindow}">
<Grid Background="{TemplateBinding Background}">
<Grid Margin="-12,-12,-12,0">
<Viewbox HorizontalAlignment="Center" Stretch="UniformToFill">
@ -87,25 +87,25 @@
Height="{TemplateBinding DecorationHeight}"
Background="{TemplateBinding BorderBrush}">
<DockPanel HorizontalAlignment="Stretch" Margin="4" LastChildFill="False">
<controls:ImageButton x:Name="PART_CloseButton"
<buttons:ImageButton x:Name="PART_CloseButton"
DockPanel.Dock="Right"
Style="{StaticResource StyleImageButtonWindow}"
Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowClose}"
ToolTip="Close" />
<controls:ImageButton x:Name="PART_MinimizeButton"
<buttons:ImageButton x:Name="PART_MinimizeButton"
DockPanel.Dock="Right"
Style="{StaticResource StyleImageButtonWindow}"
Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowMinimize}"
ToolTip="Minimize" />
<controls:ImageButton x:Name="PART_IconButton"
<buttons:ImageButton x:Name="PART_IconButton"
DockPanel.Dock="Left"
VerticalAlignment="Center"
Margin="8"
Style="{StaticResource StyleImageButtonWithOpacity}"
Image="{TemplateBinding Icon}"
ToolTip="{TemplateBinding ToolTip}" />
ToolTip="http://arge.be" />
</DockPanel>
</Border>

View File

@ -1,15 +1,15 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Arge.Controls"
xmlns:resources="clr-namespace:Arge.Resources">
xmlns:resources="clr-namespace:Arge.Resources"
xmlns:buttons="clr-namespace:Arge.Controls.Buttons">
<Style x:Key="StyleImageButton"
TargetType="{x:Type controls:ImageButton}">
TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ImageButton}">
<ControlTemplate TargetType="{x:Type buttons:ImageButton}">
<Grid Background="Transparent">
<Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}"
Source="{TemplateBinding Image}" Stretch="Uniform" />
@ -62,13 +62,13 @@
</Style>
<Style x:Key="StyleImageButtonWithOpacity"
TargetType="{x:Type controls:ImageButton}">
TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Opacity" Value="0.66" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ImageButton}">
<ControlTemplate TargetType="{x:Type buttons:ImageButton}">
<Grid Background="Transparent">
<Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}"
Source="{TemplateBinding Image}" Stretch="Uniform" />
@ -99,7 +99,7 @@
<Style x:Key="StyleImageButtonMenu"
BasedOn="{StaticResource StyleImageButton}"
TargetType="{x:Type controls:ImageButton}">
TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Width" Value="180" />
<Setter Property="Height" Value="90" />
<Setter Property="Margin" Value="0,16" />

View File

@ -1,8 +1,8 @@
using Arge.Misc;
using ReactiveUI;
namespace Arge.Themes
{
public class Theme : AbstractBindable
public class Theme : ReactiveObject
{
#region Properties & Fields

View File

@ -0,0 +1,13 @@
using ReactiveUI;
namespace Arge.ViewModels
{
public abstract class AbstractViewModel : ReactiveObject, ISupportsActivation
{
#region Properties & Fields
public ViewModelActivator Activator { get; } = new ViewModelActivator();
#endregion
}
}

View File

@ -0,0 +1,7 @@
using ReactiveUI;
namespace Arge.ViewModels
{
public class NavigationViewModel : ReactiveObject
{ }
}

View File

@ -1,8 +1,32 @@
using Arge.Misc;
using System;
using Arge.Bootstrapper;
using Arge.Enums;
using ReactiveUI;
namespace Arge.ViewModels
{
public class ShellViewModel : AbstractBindable
public class ShellViewModel : AbstractViewModel
{
#region Properties & Fields
public NavigationManager NavigationManager => NavigationManager.Instance;
#endregion
#region Constructors
public ShellViewModel()
{
this.WhenActivated(delegate (Action<IDisposable> action)
{
NavigationManager.Navigate<NavigationViewModel>(NavigationTargets.Navigation);
});
}
#endregion
#region Methods
#endregion
}
}

View File

@ -0,0 +1,17 @@
using ReactiveUI;
namespace Arge.Views
{
public class AbstractView<TViewModel> : ReactiveUserControl<TViewModel>
where TViewModel : class
{
#region Constructors
protected AbstractView()
{
this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext);
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
<local:NavigationViewBase x:Class="Arge.Views.NavigationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Arge.Views"
xmlns:viewModels="clr-namespace:Arge.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:NavigationViewModel, IsDesignTimeCreatable=true}"
d:DesignWidth="300" d:DesignHeight="72">
<Grid>
</Grid>
</local:NavigationViewBase>

View File

@ -0,0 +1,18 @@
using Arge.ViewModels;
using ReactiveUI;
namespace Arge.Views
{
public class NavigationViewBase : ReactiveUserControl<NavigationViewModel>
{ }
public partial class NavigationView : NavigationViewBase
{
public NavigationView(NavigationViewModel viewModel)
{
InitializeComponent();
this.ViewModel = viewModel;
}
}
}

View File

@ -1,11 +1,20 @@
<UserControl x:Class="Arge.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:Arge.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ShellViewModel, IsDesignTimeCreatable=true}">
</UserControl>
<views:ShellViewBase x:Class="Arge.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:Arge.ViewModels"
xmlns:views="clr-namespace:Arge.Views"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ShellViewModel, IsDesignTimeCreatable=true}">
<Grid>
<ContentControl x:Name="TargetNavigation" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="72" Margin="80,-72,72,0" />
<DockPanel LastChildFill="True">
<ContentControl x:Name="TargetLayers" DockPanel.Dock="Left" />
<ContentControl x:Name="TargetSelection" DockPanel.Dock="Right" />
<ContentControl x:Name="TargetActions" DockPanel.Dock="Bottom" />
<ContentControl x:Name="TargetSurface" />
</DockPanel>
</Grid>
</views:ShellViewBase>

View File

@ -1,14 +1,24 @@
using System.Windows.Controls;
using Arge.ViewModels;
using ReactiveUI;
namespace Arge.Views
{
public partial class ShellView : UserControl
public class ShellViewBase : AbstractView<ShellViewModel> { }
public partial class ShellView : ShellViewBase
{
#region Constructors
public ShellView()
public ShellView(ShellViewModel viewModel)
{
InitializeComponent();
this.ViewModel = viewModel;
this.WhenActivated(d =>
{
d(this.OneWayBind(ViewModel, vm => vm.NavigationManager.Navigation, v => v.TargetNavigation.Content));
});
}
#endregion

View File

@ -1,8 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caliburn.Micro" version="3.0.3" targetFramework="net45" />
<package id="Caliburn.Micro.Core" version="3.0.3" targetFramework="net45" />
<package id="CommonServiceLocator" version="1.3" targetFramework="net45" />
<package id="reactiveui" version="7.3.0" targetFramework="net45" />
<package id="reactiveui-core" version="7.3.0" targetFramework="net45" />
<package id="reactiveui-events" version="7.3.0" targetFramework="net45" />
<package id="RGB.NET.Core" version="1.0.0" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
<package id="Rx-XAML" version="2.2.5" targetFramework="net45" />
<package id="Splat" version="1.4.0" targetFramework="net45" />
<package id="Unity" version="4.0.1" targetFramework="net45" />
</packages>