mirror of https://github.com/AMT-Cheif/Stylet.git
Merge branch 'release/1.3.6'
This commit is contained in:
commit
5e97f9e1ea
|
@ -0,0 +1,2 @@
|
|||
ko_fi: canton7
|
||||
custom: ['https://www.paypal.com/donate?hosted_button_id=92FADFBYS42MU']
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
name: Report a bug
|
||||
about: If you've definitely found something wrong, use this. Not sure? Open a discussion.
|
||||
---
|
||||
|
||||
**Description**
|
||||
A clear and concise description of what the bug is. Use screenshots as necessary.
|
||||
|
||||
**To Reproduce**
|
||||
Code to reproduce the bug, which someone else can run.
|
||||
|
||||
**Version Info**
|
||||
- Stylet version: [e.g. 1.2.3]
|
||||
- Runtime version: [e.g. 5.0.300]
|
||||
|
||||
**Additional Info**
|
||||
Add any other context about the problem here.
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Open a Discussion
|
||||
url: https://github.com/canton7/stylet/discussions/new
|
||||
about: If you've got a question, suggestion, or something you're not sure about, please open a discussion.
|
|
@ -0,0 +1,9 @@
|
|||
**Checklist**
|
||||
|
||||
Thanks for contributing! Before we start, there are a few things we need to check:
|
||||
|
||||
1. This Pull Request has a corresponding Issue.
|
||||
2. You've discussed your intention to work on this feature/bug fix.
|
||||
3. This feature branch is based on develop (**not** master). The bar above should say "base: develop".
|
||||
|
||||
Thanks!
|
|
@ -12,10 +12,10 @@ namespace Bootstrappers
|
|||
{
|
||||
private IContainer container;
|
||||
|
||||
private object _rootViewModel;
|
||||
protected virtual object RootViewModel
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.GetInstance(typeof(TRootViewModel))); }
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
@ -43,7 +43,9 @@ namespace Bootstrappers
|
|||
builder.RegisterType<WindowManager>().As<IWindowManager>().SingleInstance();
|
||||
builder.RegisterType<EventAggregator>().As<IEventAggregator>().SingleInstance();
|
||||
builder.RegisterType<MessageBoxViewModel>().As<IMessageBoxViewModel>().ExternallyOwned(); // Not singleton!
|
||||
builder.RegisterAssemblyTypes(this.GetType().Assembly).ExternallyOwned();
|
||||
|
||||
// See https://github.com/canton7/Stylet/discussions/211
|
||||
builder.RegisterAssemblyTypes(this.GetType().Assembly).Where(x => !x.Name.Contains("ProcessedByFody")).ExternallyOwned();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Bootstrappers</RootNamespace>
|
||||
<AssemblyName>Bootstrappers</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -30,42 +31,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.2.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Autofac.4.2.1\lib\net45\Autofac.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Windsor">
|
||||
<HintPath>packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity">
|
||||
<HintPath>packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity.Configuration">
|
||||
<HintPath>packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity.RegistrationByConvention">
|
||||
<HintPath>packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject">
|
||||
<HintPath>packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="StructureMap, Version=3.1.6.186, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\structuremap.3.1.6.186\lib\net40\StructureMap.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="StructureMap.Net4, Version=3.1.6.186, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\structuremap.3.1.6.186\lib\net40\StructureMap.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
@ -80,20 +46,19 @@
|
|||
<Compile Include="NinjectBootstrapper.cs" />
|
||||
<Compile Include="NoIoCContainerBootstrapper.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MicrosoftDependencyInjectionBootstrapper.cs" />
|
||||
<Compile Include="StructureMapBootstrapper.cs" />
|
||||
<Compile Include="Tests\AutofacTests.cs" />
|
||||
<Compile Include="Tests\BootstrapperTests.cs" />
|
||||
<Compile Include="Tests\CastleWindsorTests.cs" />
|
||||
<Compile Include="Tests\NinjectTests.cs" />
|
||||
<Compile Include="Tests\NoIoCContainerTests.cs" />
|
||||
<Compile Include="Tests\MicrosoftDependencyInjectionTests.cs" />
|
||||
<Compile Include="Tests\StructureMapTests.cs" />
|
||||
<Compile Include="Tests\StubType.cs" />
|
||||
<Compile Include="Tests\UnityTests.cs" />
|
||||
<Compile Include="UnityBootstrapper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -14,10 +14,10 @@ namespace Bootstrappers
|
|||
{
|
||||
private IWindsorContainer container;
|
||||
|
||||
private object _rootViewModel;
|
||||
protected virtual object RootViewModel
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.GetInstance(typeof(TRootViewModel))); }
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
@ -39,7 +39,7 @@ namespace Bootstrappers
|
|||
};
|
||||
|
||||
// Stylet does its own disposal of ViewModels: Castle Windsor shouldn't be doing the same
|
||||
// Castle Windsor seems to be ver opinionated on this point, insisting that the container
|
||||
// Castle Windsor seems to be very opinionated on this point, insisting that the container
|
||||
// should be responsible for disposing all components. This is at odds with Stylet's approach
|
||||
// (and indeed common sense).
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
using Autofac;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bootstrappers
|
||||
{
|
||||
public class MicrosoftDependencyInjectionBootstrapper<TRootViewModel> : BootstrapperBase where TRootViewModel : class
|
||||
{
|
||||
private ServiceProvider serviceProvider;
|
||||
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
public IServiceProvider ServiceProvider
|
||||
{
|
||||
get { return this.serviceProvider; }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
this.DefaultConfigureIoC(services);
|
||||
this.ConfigureIoC(services);
|
||||
this.serviceProvider = services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carries out default configuration of the IoC container. Override if you don't want to do this
|
||||
/// </summary>
|
||||
protected virtual void DefaultConfigureIoC(IServiceCollection services)
|
||||
{
|
||||
var viewManagerConfig = new ViewManagerConfig()
|
||||
{
|
||||
ViewFactory = this.GetInstance,
|
||||
ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
|
||||
};
|
||||
|
||||
services.AddSingleton<IViewManager>(new ViewManager(viewManagerConfig));
|
||||
services.AddTransient<MessageBoxView>();
|
||||
|
||||
services.AddSingleton<IWindowManagerConfig>(this);
|
||||
services.AddSingleton<IWindowManager, WindowManager>();
|
||||
services.AddSingleton<IEventAggregator, EventAggregator>();
|
||||
services.AddTransient<IMessageBoxViewModel, MessageBoxViewModel>(); // Not singleton!
|
||||
// Also need a factory
|
||||
services.AddSingleton<Func<IMessageBoxViewModel>>(() => new MessageBoxViewModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to add your own types to the IoC container.
|
||||
/// </summary>
|
||||
protected virtual void ConfigureIoC(IServiceCollection services) { }
|
||||
|
||||
public override object GetInstance(Type type)
|
||||
{
|
||||
return this.serviceProvider.GetRequiredService(type);
|
||||
}
|
||||
|
||||
protected override void Launch()
|
||||
{
|
||||
base.DisplayRootView(this.RootViewModel);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
ScreenExtensions.TryDispose(this._rootViewModel);
|
||||
if (this.serviceProvider != null)
|
||||
this.serviceProvider.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,10 +11,10 @@ namespace Bootstrappers
|
|||
{
|
||||
private IKernel kernel;
|
||||
|
||||
private object _rootViewModel;
|
||||
protected virtual object RootViewModel
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.GetInstance(typeof(TRootViewModel))); }
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
|
|
@ -12,10 +12,10 @@ namespace Bootstrappers
|
|||
{
|
||||
private IContainer container;
|
||||
|
||||
private object _rootViewModel;
|
||||
protected virtual object RootViewModel
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.GetInstance(typeof(TRootViewModel))); }
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
|
|
@ -159,6 +159,9 @@ namespace Bootstrappers.Tests
|
|||
[Test]
|
||||
public void DoesNotDisposeTransientInstances()
|
||||
{
|
||||
if (!this.Autobinds)
|
||||
Assert.Ignore("Autobinding not supported");
|
||||
|
||||
StubType.Reset();
|
||||
|
||||
var vm = this.bootstrapper.GetInstance(typeof(StubType));
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
using Autofac;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bootstrappers.Tests
|
||||
{
|
||||
public class MyMicrosoftDependencyInjectionBootstrapper : MicrosoftDependencyInjectionBootstrapper<TestRootViewModel>, ITestBootstrapper
|
||||
{
|
||||
public List<string> ConfigureLog { get; set; }
|
||||
|
||||
public int DisposeCount { get; private set; }
|
||||
|
||||
public MyMicrosoftDependencyInjectionBootstrapper()
|
||||
{
|
||||
this.ConfigureLog = new List<string>();
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
base.Configure();
|
||||
this.ConfigureLog.Add("Configure");
|
||||
}
|
||||
|
||||
protected override void DefaultConfigureIoC(IServiceCollection services)
|
||||
{
|
||||
base.DefaultConfigureIoC(services);
|
||||
this.ConfigureLog.Add("DefaultConfigureIoC");
|
||||
}
|
||||
|
||||
protected override void ConfigureIoC(IServiceCollection services)
|
||||
{
|
||||
base.ConfigureIoC(services);
|
||||
this.ConfigureLog.Add("ConfigureIoC");
|
||||
}
|
||||
|
||||
public new object GetInstance(Type type)
|
||||
{
|
||||
return base.GetInstance(type);
|
||||
}
|
||||
|
||||
public new void ConfigureBootstrapper()
|
||||
{
|
||||
base.ConfigureBootstrapper();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
this.DisposeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture(Category = "ServiceCollection")]
|
||||
public class MicrosoftDependencyInjectionTests : BootstrapperTests<MyMicrosoftDependencyInjectionBootstrapper>
|
||||
{
|
||||
public MicrosoftDependencyInjectionTests()
|
||||
{
|
||||
this.Autobinds = false;
|
||||
}
|
||||
|
||||
public override MyMicrosoftDependencyInjectionBootstrapper CreateBootstrapper()
|
||||
{
|
||||
return new MyMicrosoftDependencyInjectionBootstrapper();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,10 +11,10 @@ namespace Bootstrappers
|
|||
{
|
||||
private IUnityContainer container;
|
||||
|
||||
private object _rootViewModel;
|
||||
protected virtual object RootViewModel
|
||||
private TRootViewModel _rootViewModel;
|
||||
protected virtual TRootViewModel RootViewModel
|
||||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.GetInstance(typeof(TRootViewModel))); }
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = (TRootViewModel)this.GetInstance(typeof(TRootViewModel))); }
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.2.1" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="3.3.3" targetFramework="net45" />
|
||||
<package id="Castle.Windsor" version="3.3.0" targetFramework="net45" />
|
||||
<package id="Ninject" version="3.2.2.0" targetFramework="net45" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net45" />
|
||||
<package id="NUnit3TestAdapter" version="3.6.0" targetFramework="net45" />
|
||||
<package id="structuremap" version="3.1.6.186" targetFramework="net45" />
|
||||
<package id="Unity" version="3.5.1404.0" targetFramework="net45" />
|
||||
</packages>
|
|
@ -1,6 +1,20 @@
|
|||
Stylet Changelog
|
||||
================
|
||||
|
||||
v1.3.6
|
||||
------
|
||||
|
||||
- If an Action returns a Task, await it in an `async void` method (#53)
|
||||
- Allow Actions to have explicit targets (`{s:Action ..., Target=...}`) (#177)
|
||||
- Allow Actions to invoke static methods (#177)
|
||||
- Actions: if the target does not implement `INotifyPropertyChanged`, still try and evaluate guard properties (#214)
|
||||
- Add an extra layer to the bootstrapper class hierarchy between `BootstrapperBase` and `Bootstrapper<T>`,
|
||||
for people who don't have a root ViewModel
|
||||
- Allow starting the Bootstrapper without an Application (#206)
|
||||
- Expose SynchronousDispatcher and ApplicationDispatcher to assign to `Execute.Dispatcher` (#217)
|
||||
- Improve the sample bootstrappers (fix Autofac, add Microsoft.Services.DependencyInjection)
|
||||
- Improve samples
|
||||
|
||||
v1.3.5
|
||||
------
|
||||
|
||||
|
|
11
Rakefile
11
Rakefile
|
@ -19,21 +19,20 @@ directory COVERAGE_DIR
|
|||
|
||||
desc "Build the project using the current CONFIG (or Debug)"
|
||||
task :build do
|
||||
# https://github.com/novotnyllc/MSBuildSdkExtras/pull/249
|
||||
sh 'dotnet', 'build', '-c', CONFIG, CSPROJ, '/nowarn:MSB4011'
|
||||
sh 'dotnet', 'build', '-c', CONFIG, CSPROJ
|
||||
end
|
||||
|
||||
desc "Run unit tests using the current CONFIG (or Debug)"
|
||||
task :test do
|
||||
sh 'dotnet', 'test', '-c', CONFIG, UNIT_TESTS, '/nowarn:MSB4011'
|
||||
sh 'dotnet', 'test', '-c', CONFIG, UNIT_TESTS
|
||||
end
|
||||
|
||||
desc "Create NuGet package"
|
||||
task :package do
|
||||
# Not sure why these have to be this way around, but they do
|
||||
sh 'dotnet', 'pack', '--no-build', '-c', CONFIG, CSPROJ, "-p:NuSpecFile=../#{NUSPEC_START}", '/nowarn:MSB4011'
|
||||
sh 'dotnet', 'pack', '--no-build', '-c', CONFIG, CSPROJ, '-p:IncludeSymbols=true', '/nowarn:MSB4011'
|
||||
sh 'dotnet', 'pack', '-c', CONFIG, TEMPLATES_CSPROJ, '/nowarn:MSB4011'
|
||||
sh 'dotnet', 'pack', '--no-build', '-c', CONFIG, CSPROJ, "-p:NuSpecFile=../#{NUSPEC_START}"
|
||||
sh 'dotnet', 'pack', '--no-build', '-c', CONFIG, CSPROJ, '-p:IncludeSymbols=true'
|
||||
sh 'dotnet', 'pack', '-c', CONFIG, TEMPLATES_CSPROJ
|
||||
end
|
||||
|
||||
desc "Bump version number"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</DockPanel>
|
||||
|
||||
<Grid DockPanel.Dock="Bottom">
|
||||
<Button HorizontalAlignment="Left" Width="100" IsDefault="True" Command="{s:Action Close}">Save</Button>
|
||||
<Button HorizontalAlignment="Left" Width="100" IsDefault="True" Command="{s:Action Save}">Save</Button>
|
||||
<Button HorizontalAlignment="Right" Width="100" IsCancel="True">Cancel</Button>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
|
|
|
@ -15,5 +15,10 @@ namespace Stylet.Samples.HelloDialog
|
|||
{
|
||||
this.RequestClose(null);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
this.RequestClose(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,9 @@ namespace Stylet.Samples.HelloDialog
|
|||
this.NameString = "Click the button to show the dialog";
|
||||
}
|
||||
|
||||
public void ShowDialog()
|
||||
public async System.Threading.Tasks.Task ShowDialog()
|
||||
{
|
||||
throw new Exception("KABLAMMO");
|
||||
var dialogVm = this.dialogFactory.CreateDialog1();
|
||||
var result = this.windowManager.ShowDialog(dialogVm);
|
||||
if (result.GetValueOrDefault())
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,13 @@
|
|||
<Application x:Class="Stylet.Samples.NavigationController.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Stylet.Samples.NavigationController"
|
||||
xmlns:s="https://github.com/canton7/Stylet">
|
||||
<Application.Resources>
|
||||
<s:ApplicationLoader>
|
||||
<s:ApplicationLoader.Bootstrapper>
|
||||
<local:Bootstrapper />
|
||||
</s:ApplicationLoader.Bootstrapper>
|
||||
</s:ApplicationLoader>
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Stylet.Samples.NavigationController
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using Stylet.Samples.NavigationController.Pages;
|
||||
|
||||
namespace Stylet.Samples.NavigationController
|
||||
{
|
||||
public class Bootstrapper : Bootstrapper<ShellViewModel>
|
||||
{
|
||||
protected override void ConfigureIoC(IStyletIoCBuilder builder)
|
||||
{
|
||||
builder.Bind<NavigationController>().And<INavigationController>().To<NavigationController>().InSingletonScope();
|
||||
// https://github.com/canton7/Stylet/issues/24
|
||||
builder.Bind<Func<Page1ViewModel>>().ToFactory<Func<Page1ViewModel>>(c => () => c.Get<Page1ViewModel>());
|
||||
builder.Bind<Func<Page2ViewModel>>().ToFactory<Func<Page2ViewModel>>(c => () => c.Get<Page2ViewModel>());
|
||||
}
|
||||
|
||||
protected override void OnLaunch()
|
||||
{
|
||||
// There's a circular dependency, where ShellViewModel -> HeaderViewModel -> NavigationController -> ShellViewModel
|
||||
// We break this by assigning the ShellViewModel to the NavigationController after constructing it
|
||||
var navigationController = this.Container.Get<NavigationController>();
|
||||
navigationController.Delegate = this.RootViewModel;
|
||||
navigationController.NavigateToPage1();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using Stylet.Samples.NavigationController.Pages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Stylet.Samples.NavigationController
|
||||
{
|
||||
public interface INavigationController
|
||||
{
|
||||
void NavigateToPage1();
|
||||
void NavigateToPage2(string initiator);
|
||||
}
|
||||
|
||||
public interface INavigationControllerDelegate
|
||||
{
|
||||
void NavigateTo(IScreen screen);
|
||||
}
|
||||
|
||||
public class NavigationController : INavigationController
|
||||
{
|
||||
private readonly Func<Page1ViewModel> page1ViewModelFactory;
|
||||
private readonly Func<Page2ViewModel> page2ViewModelFactory;
|
||||
|
||||
public INavigationControllerDelegate Delegate { get; set; }
|
||||
|
||||
public NavigationController(Func<Page1ViewModel> page1ViewModelFactory, Func<Page2ViewModel> page2ViewModelFactory)
|
||||
{
|
||||
this.page1ViewModelFactory = page1ViewModelFactory ?? throw new ArgumentNullException(nameof(page1ViewModelFactory));
|
||||
this.page2ViewModelFactory = page2ViewModelFactory ?? throw new ArgumentNullException(nameof(page2ViewModelFactory));
|
||||
}
|
||||
|
||||
public void NavigateToPage1()
|
||||
{
|
||||
this.Delegate?.NavigateTo(this.page1ViewModelFactory());
|
||||
}
|
||||
|
||||
public void NavigateToPage2(string initiator)
|
||||
{
|
||||
var vm = this.page2ViewModelFactory();
|
||||
vm.Initiator = initiator;
|
||||
this.Delegate?.NavigateTo(vm);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<UserControl x:Class="Stylet.Samples.NavigationController.Pages.HeaderView"
|
||||
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:Stylet.Samples.NavigationController.Pages"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock>Go to: </TextBlock>
|
||||
<Button Margin="5,0" Command="{s:Action NavigateToPage1}">Page 1</Button>
|
||||
<Button Margin="5,0" Command="{s:Action NavigateToPage2}">Page 2</Button>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Pages
|
||||
{
|
||||
public class HeaderViewModel : Screen
|
||||
{
|
||||
private readonly INavigationController navigationController;
|
||||
|
||||
public HeaderViewModel(INavigationController navigationController)
|
||||
{
|
||||
this.navigationController = navigationController ?? throw new ArgumentNullException(nameof(navigationController));
|
||||
}
|
||||
|
||||
public void NavigateToPage1() => this.navigationController.NavigateToPage1();
|
||||
public void NavigateToPage2() => this.navigationController.NavigateToPage2("the Header");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<UserControl x:Class="Stylet.Samples.NavigationController.Pages.Page1View"
|
||||
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:s="https://github.com/canton7/Stylet"
|
||||
xmlns:local="clr-namespace:Stylet.Samples.NavigationController.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<StackPanel>
|
||||
<TextBlock>This is page 1</TextBlock>
|
||||
<Button Command="{s:Action NavigateToPage2}">Go to page 2</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Pages
|
||||
{
|
||||
public class Page1ViewModel : Screen
|
||||
{
|
||||
private readonly INavigationController navigationController;
|
||||
|
||||
public Page1ViewModel(INavigationController navigationController)
|
||||
{
|
||||
this.navigationController = navigationController ?? throw new ArgumentNullException(nameof(navigationController));
|
||||
}
|
||||
|
||||
public void NavigateToPage2() => this.navigationController.NavigateToPage2("Page 1");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<UserControl x:Class="Stylet.Samples.NavigationController.Pages.Page2View"
|
||||
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:s="https://github.com/canton7/Stylet"
|
||||
xmlns:local="clr-namespace:Stylet.Samples.NavigationController.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<StackPanel>
|
||||
<TextBlock>This is page 2</TextBlock>
|
||||
<TextBlock Text="{Binding Initiator, StringFormat='You got here from {0}'}"/>
|
||||
<Button Command="{s:Action NavigateToPage1}">Go to page 1</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Pages
|
||||
{
|
||||
public class Page2ViewModel : Screen
|
||||
{
|
||||
private readonly INavigationController navigationController;
|
||||
|
||||
private string _initiator;
|
||||
public string Initiator
|
||||
{
|
||||
get => this._initiator;
|
||||
set => this.SetAndNotify(ref this._initiator, value);
|
||||
}
|
||||
|
||||
public Page2ViewModel(INavigationController navigationController)
|
||||
{
|
||||
this.navigationController = navigationController ?? throw new ArgumentNullException(nameof(navigationController));
|
||||
}
|
||||
|
||||
public void NavigateToPage1() => this.navigationController.NavigateToPage1();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<Window x:Class="Stylet.Samples.NavigationController.Pages.ShellView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Stylet.Samples.NavigationController.Pages"
|
||||
mc:Ignorable="d"
|
||||
Title="Navigation Controller sample" Height="450" Width="800"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
d:DataContext="{d:DesignInstance local:ShellViewModel}">
|
||||
<DockPanel>
|
||||
<ContentControl DockPanel.Dock="Top" s:View.Model="{Binding HeaderViewModel}"/>
|
||||
<ContentControl s:View.Model="{Binding ActiveItem}"/>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using Stylet;
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Pages
|
||||
{
|
||||
public class ShellViewModel : Conductor<IScreen>, INavigationControllerDelegate
|
||||
{
|
||||
public HeaderViewModel HeaderViewModel { get; }
|
||||
|
||||
public ShellViewModel(HeaderViewModel headerViewModel)
|
||||
{
|
||||
this.HeaderViewModel = headerViewModel ?? throw new ArgumentNullException(nameof(headerViewModel));
|
||||
}
|
||||
|
||||
public void NavigateTo(IScreen screen)
|
||||
{
|
||||
this.ActivateItem(screen);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 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("Stylet.Samples.NavigationController")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Stylet.Samples.NavigationController")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[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)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[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)
|
||||
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)
|
||||
)]
|
||||
|
||||
|
||||
// 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 Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
70
Samples/Stylet.Samples.NavigationController/Properties/Resources.Designer.cs
generated
Normal file
70
Samples/Stylet.Samples.NavigationController/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,70 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Properties
|
||||
{
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stylet.Samples.NavigationController.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
29
Samples/Stylet.Samples.NavigationController/Properties/Settings.Designer.cs
generated
Normal file
29
Samples/Stylet.Samples.NavigationController/Properties/Settings.Designer.cs
generated
Normal file
|
@ -0,0 +1,29 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Stylet.Samples.NavigationController.Properties
|
||||
{
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -0,0 +1,119 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Stylet.Samples.NavigationController</RootNamespace>
|
||||
<AssemblyName>Stylet.Samples.NavigationController</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Bootstrapper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="NavigationController.cs" />
|
||||
<Compile Include="Pages\HeaderViewModel.cs" />
|
||||
<Compile Include="Pages\Page1ViewModel.cs" />
|
||||
<Compile Include="Pages\Page2ViewModel.cs" />
|
||||
<Compile Include="Pages\ShellViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Pages\HeaderView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\Page1View.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\Page2View.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\ShellView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stylet\Stylet.csproj">
|
||||
<Project>{2435bd00-ac12-48b0-ad36-9bab2fdec3f5}</Project>
|
||||
<Name>Stylet</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -1,70 +1,79 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet", "..\Stylet\Stylet.csproj", "{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.Hello", "Stylet.Samples.Hello\Stylet.Samples.Hello.csproj", "{6C7FBB21-52AC-4333-A42A-9F5E9D048621}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.TabNavigation", "Stylet.Samples.TabNavigation\Stylet.Samples.TabNavigation.csproj", "{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.MasterDetail", "Stylet.Samples.MasterDetail\Stylet.Samples.MasterDetail.csproj", "{A281DFF2-125E-4412-8927-0F09EEFC5AD1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.HelloDialog", "Stylet.Samples.HelloDialog\Stylet.Samples.HelloDialog.csproj", "{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.OverridingViewManager", "Stylet.Samples.OverridingViewManager\Stylet.Samples.OverridingViewManager.csproj", "{2F7D7EF3-730A-45E3-93CA-7C5031250246}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.RedditBrowser", "Stylet.Samples.RedditBrowser\Stylet.Samples.RedditBrowser.csproj", "{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.ModelValidation", "Stylet.Samples.ModelValidation\Stylet.Samples.ModelValidation.csproj", "{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.DesignMode", "Stylet.Samples.DesignMode\Stylet.Samples.DesignMode.csproj", "{D5225DA1-58ED-42AA-9589-A4F86E7667F7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30709.64
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stylet", "..\Stylet\Stylet.csproj", "{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.Hello", "Stylet.Samples.Hello\Stylet.Samples.Hello.csproj", "{6C7FBB21-52AC-4333-A42A-9F5E9D048621}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.TabNavigation", "Stylet.Samples.TabNavigation\Stylet.Samples.TabNavigation.csproj", "{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.MasterDetail", "Stylet.Samples.MasterDetail\Stylet.Samples.MasterDetail.csproj", "{A281DFF2-125E-4412-8927-0F09EEFC5AD1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.HelloDialog", "Stylet.Samples.HelloDialog\Stylet.Samples.HelloDialog.csproj", "{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.OverridingViewManager", "Stylet.Samples.OverridingViewManager\Stylet.Samples.OverridingViewManager.csproj", "{2F7D7EF3-730A-45E3-93CA-7C5031250246}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.RedditBrowser", "Stylet.Samples.RedditBrowser\Stylet.Samples.RedditBrowser.csproj", "{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.ModelValidation", "Stylet.Samples.ModelValidation\Stylet.Samples.ModelValidation.csproj", "{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.DesignMode", "Stylet.Samples.DesignMode\Stylet.Samples.DesignMode.csproj", "{D5225DA1-58ED-42AA-9589-A4F86E7667F7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.NavigationController", "Stylet.Samples.NavigationController\Stylet.Samples.NavigationController.csproj", "{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2435BD00-AC12-48B0-AD36-9BAB2FDEC3F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A281DFF2-125E-4412-8927-0F09EEFC5AD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F6DD6F38-40A3-4EC1-B342-0C2BCCF0DD44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F7D7EF3-730A-45E3-93CA-7C5031250246}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72B1C6E4-1293-47DD-BEFD-FA2E782BDBDA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EA5A6CA5-7E8E-4401-A3D2-0035DDE10413}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5225DA1-58ED-42AA-9589-A4F86E7667F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9DEE75AC-6BC1-4375-B6A0-44EAF39FF559}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A72165C7-7E4E-4336-88FF-BDCC3E300D54}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -8,14 +8,12 @@ namespace Stylet
|
|||
/// <summary>
|
||||
/// Bootstrapper to be extended by any application which wants to use StyletIoC (the default)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you don't have a root ViewModel, you might prefer to override <see cref="StyletIoCBootstrapperBase"/>
|
||||
/// </remarks>
|
||||
/// <typeparam name="TRootViewModel">Type of the root ViewModel. This will be instantiated and displayed</typeparam>
|
||||
public abstract class Bootstrapper<TRootViewModel> : BootstrapperBase where TRootViewModel : class
|
||||
public abstract class Bootstrapper<TRootViewModel> : StyletIoCBootstrapperBase where TRootViewModel : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Bootstrapper's IoC container. This is created after ConfigureIoC has been run.
|
||||
/// </summary>
|
||||
protected IContainer Container { get; set; }
|
||||
|
||||
private TRootViewModel _rootViewModel;
|
||||
|
||||
/// <summary>
|
||||
|
@ -25,65 +23,7 @@ namespace Stylet
|
|||
{
|
||||
get { return this._rootViewModel ?? (this._rootViewModel = this.Container.Get<TRootViewModel>()); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden from BootstrapperBase, this sets up the IoC container
|
||||
/// </summary>
|
||||
protected override sealed void ConfigureBootstrapper()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Assemblies = new List<Assembly>(new List<Assembly>() { this.GetType().Assembly });
|
||||
|
||||
// Call DefaultConfigureIoC *after* ConfigureIoIC, so that they can customize builder.Assemblies
|
||||
this.ConfigureIoC(builder);
|
||||
this.DefaultConfigureIoC(builder);
|
||||
|
||||
this.Container = builder.BuildContainer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carries out default configuration of StyletIoC. Override if you don't want to do this
|
||||
/// </summary>
|
||||
/// <param name="builder">StyletIoC builder to use to configure the container</param>
|
||||
protected virtual void DefaultConfigureIoC(StyletIoCBuilder builder)
|
||||
{
|
||||
// Mark these as weak-bindings, so the user can replace them if they want
|
||||
var viewManagerConfig = new ViewManagerConfig()
|
||||
{
|
||||
ViewFactory = this.GetInstance,
|
||||
ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
|
||||
};
|
||||
builder.Bind<ViewManagerConfig>().ToInstance(viewManagerConfig).AsWeakBinding();
|
||||
|
||||
// Bind it to both IViewManager and to itself, so that people can get it with Container.Get<ViewManager>()
|
||||
builder.Bind<IViewManager>().And<ViewManager>().To<ViewManager>().InSingletonScope().AsWeakBinding();
|
||||
|
||||
builder.Bind<IWindowManagerConfig>().ToInstance(this).DisposeWithContainer(false).AsWeakBinding();
|
||||
builder.Bind<IWindowManager>().To<WindowManager>().InSingletonScope().AsWeakBinding();
|
||||
builder.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope().AsWeakBinding();
|
||||
builder.Bind<IMessageBoxViewModel>().To<MessageBoxViewModel>().AsWeakBinding();
|
||||
// Stylet's assembly isn't added to the container, so add this explicitly
|
||||
builder.Bind<MessageBoxView>().ToSelf();
|
||||
|
||||
builder.Autobind();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to add your own types to the IoC container.
|
||||
/// </summary>
|
||||
/// <param name="builder">StyletIoC builder to use to configure the container</param>
|
||||
protected virtual void ConfigureIoC(IStyletIoCBuilder builder) { }
|
||||
|
||||
/// <summary>
|
||||
/// Given a type, use the IoC container to fetch an instance of it
|
||||
/// </summary>
|
||||
/// <param name="type">Type to fetch</param>
|
||||
/// <returns>Fetched instance</returns>
|
||||
public override object GetInstance(Type type)
|
||||
{
|
||||
return this.Container.Get(type);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when the application is launched. Displays the root view.
|
||||
/// </summary>
|
||||
|
@ -97,12 +37,11 @@ namespace Stylet
|
|||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
// Dispose the container last
|
||||
base.Dispose();
|
||||
// Don't create the root ViewModel if it doesn't already exist...
|
||||
ScreenExtensions.TryDispose(this._rootViewModel);
|
||||
if (this.Container != null)
|
||||
this.Container.Dispose();
|
||||
|
||||
// Dispose the container last
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,13 @@ namespace Stylet
|
|||
/// <summary>
|
||||
/// Called by the ApplicationLoader when this bootstrapper is loaded
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you're constructing the bootstrapper yourself, call this manully and pass in the Application
|
||||
/// (probably <see cref="Application.Current"/>). Stylet will start when <see cref="Application.Startup"/>
|
||||
/// is fired. If no Application is available, do not call this but instead call <see cref="Start(string[])"/>.
|
||||
/// (In this case, note that the <see cref="Execute"/> methods will all dispatch synchronously, unless you
|
||||
/// set <see cref="Execute.Dispatcher"/> yourself).
|
||||
/// </remarks>
|
||||
/// <param name="application">Application within which Stylet is running</param>
|
||||
public void Setup(Application application)
|
||||
{
|
||||
|
@ -43,7 +50,7 @@ namespace Stylet
|
|||
this.Application = application;
|
||||
|
||||
// Use the current application's dispatcher for Execute
|
||||
Execute.Dispatcher = new DispatcherWrapper(this.Application.Dispatcher);
|
||||
Execute.Dispatcher = new ApplicationDispatcher(this.Application.Dispatcher);
|
||||
|
||||
this.Application.Startup += (o, e) => this.Start(e.Args);
|
||||
// Make life nice for the app - they can handle these by overriding Bootstrapper methods, rather than adding event handlers
|
||||
|
@ -64,6 +71,10 @@ namespace Stylet
|
|||
/// <summary>
|
||||
/// Called on Application.Startup, this does everything necessary to start the application
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you're constructing the bootstrapper yourself, and aren't able to call <see cref="Setup(Application)"/>,
|
||||
/// (e.g. because an Application isn't available), you must call this yourself.
|
||||
/// </remarks>
|
||||
/// <param name="args">Command-line arguments used to start this executable</param>
|
||||
public virtual void Start(string[] args)
|
||||
{
|
||||
|
@ -73,9 +84,8 @@ namespace Stylet
|
|||
|
||||
this.ConfigureBootstrapper();
|
||||
|
||||
// Cater for the unit tests, which can't sensibly stub Application
|
||||
if (this.Application != null)
|
||||
this.Application.Resources.Add(View.ViewManagerResourceKey, this.GetInstance(typeof(IViewManager)));
|
||||
// We allow starting without an application
|
||||
this.Application?.Resources.Add(View.ViewManagerResourceKey, this.GetInstance(typeof(IViewManager)));
|
||||
|
||||
this.Configure();
|
||||
this.Launch();
|
||||
|
@ -107,7 +117,7 @@ namespace Stylet
|
|||
/// <returns>The currently-displayed window, or null</returns>
|
||||
public virtual Window GetActiveWindow()
|
||||
{
|
||||
return this.Application.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive) ?? this.Application.MainWindow;
|
||||
return this.Application?.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive) ?? this.Application?.MainWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -16,11 +16,13 @@ namespace Stylet
|
|||
/// Gets or sets Execute's dispatcher
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should be set to the UI thread's Dispatcher. This is normally done by the Bootstrapper.
|
||||
/// Should be set a <see cref="ApplicationDispatcher"/> wrapping the current application's dispatcher, which is
|
||||
/// normally done by the Bootstrapper. Can also be set to <see cref="SynchronousDispatcher.Instance"/>, or a
|
||||
/// custom <see cref="IDispatcher"/> implementation.
|
||||
/// </remarks>
|
||||
public static IDispatcher Dispatcher
|
||||
{
|
||||
get { return _dispatcher ?? (_dispatcher = new SynchronousDispatcher()); }
|
||||
get { return _dispatcher ?? SynchronousDispatcher.Instance; }
|
||||
|
||||
set
|
||||
{
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Stylet
|
||||
{
|
||||
/// <summary>
|
||||
/// Generalised dispatcher, which can post and send
|
||||
/// Generalised dispatcher, which can post and send.
|
||||
/// Used by <see cref="Execute"/>.
|
||||
/// </summary>
|
||||
public interface IDispatcher
|
||||
{
|
||||
|
@ -26,43 +28,75 @@ namespace Stylet
|
|||
bool IsCurrent { get; }
|
||||
}
|
||||
|
||||
internal class DispatcherWrapper : IDispatcher
|
||||
/// <summary>
|
||||
/// <see cref="IDispatcher"/> implementation which can dispatch using <see cref="Dispatcher"/>
|
||||
/// </summary>
|
||||
public class ApplicationDispatcher : IDispatcher
|
||||
{
|
||||
private readonly Dispatcher dispatcher;
|
||||
|
||||
public DispatcherWrapper(Dispatcher dispatcher)
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="ApplicationDispatcher"/> class with the given <see cref="Dispatcher"/>
|
||||
/// </summary>
|
||||
/// <param name="dispatcher"><see cref="Dispatcher"/> to use, normally Application.Current.Dispatcher</param>
|
||||
public ApplicationDispatcher(Dispatcher dispatcher)
|
||||
{
|
||||
this.dispatcher = dispatcher;
|
||||
this.dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="ApplicationDispatcher"/> class with the given <see cref="Application"/>
|
||||
/// </summary>
|
||||
/// <param name="application"><see cref="Application"/> to use, normally Application</param>
|
||||
public ApplicationDispatcher(Application application)
|
||||
: this(application?.Dispatcher ?? throw new ArgumentNullException(nameof(application)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Post(Action action)
|
||||
{
|
||||
this.dispatcher.BeginInvoke(action);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Send(Action action)
|
||||
{
|
||||
this.dispatcher.Invoke(action);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsCurrent
|
||||
{
|
||||
get { return this.dispatcher.CheckAccess(); }
|
||||
}
|
||||
}
|
||||
|
||||
internal class SynchronousDispatcher : IDispatcher
|
||||
/// <summary>
|
||||
/// <see cref="IDispatcher"/> implementation whcih dispatches synchronously.
|
||||
/// Usually used for unit testing.
|
||||
/// </summary>
|
||||
public class SynchronousDispatcher : IDispatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the singleton instance of <see cref="SynchronousDispatcher"/>
|
||||
/// </summary>
|
||||
public static SynchronousDispatcher Instance { get; } = new SynchronousDispatcher();
|
||||
private SynchronousDispatcher() { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Post(Action action)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Send(Action action)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsCurrent
|
||||
{
|
||||
get { return true; }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/2.1.2">
|
||||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
@ -23,16 +23,12 @@
|
|||
|
||||
<!-- Just embed all sources in the PDB: snupkg files don't support bare .cs files, and SourceLink is annoying -->
|
||||
<!-- We set IncludeSymbols in the Rakefile, because we don't want it to apply to Stylet.Start -->
|
||||
<!-- Note that stack traces don't work on < net471, but snupkg only supports portable, so nothing we can do -->
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
|
||||
<!-- Stack traces on < net471 don't work with portable -->
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Stylet
|
||||
{
|
||||
/// <summary>
|
||||
/// Bootstrapper to be extended by any application which wants to use StyletIoC, but doesn't have a root ViewModel
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You would normally use <see cref="Bootstrapper{TRootViewModel}"/>, which lets you specify the root ViewModel
|
||||
/// to display. If you don't want to show a window on startup, override <see cref="BootstrapperBase.Launch"/>
|
||||
/// but don't call <see cref="BootstrapperBase.DisplayRootView(object)"/>.
|
||||
/// </remarks>
|
||||
public abstract class StyletIoCBootstrapperBase : BootstrapperBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Bootstrapper's IoC container. This is created after ConfigureIoC has been run.
|
||||
/// </summary>
|
||||
protected IContainer Container { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overridden from BootstrapperBase, this sets up the IoC container
|
||||
/// </summary>
|
||||
protected override sealed void ConfigureBootstrapper()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Assemblies = new List<Assembly>(new List<Assembly>() { this.GetType().Assembly });
|
||||
|
||||
// Call DefaultConfigureIoC *after* ConfigureIoIC, so that they can customize builder.Assemblies
|
||||
this.ConfigureIoC(builder);
|
||||
this.DefaultConfigureIoC(builder);
|
||||
|
||||
this.Container = builder.BuildContainer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carries out default configuration of StyletIoC. Override if you don't want to do this
|
||||
/// </summary>
|
||||
/// <param name="builder">StyletIoC builder to use to configure the container</param>
|
||||
protected virtual void DefaultConfigureIoC(StyletIoCBuilder builder)
|
||||
{
|
||||
// Mark these as weak-bindings, so the user can replace them if they want
|
||||
var viewManagerConfig = new ViewManagerConfig()
|
||||
{
|
||||
ViewFactory = this.GetInstance,
|
||||
ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
|
||||
};
|
||||
builder.Bind<ViewManagerConfig>().ToInstance(viewManagerConfig).AsWeakBinding();
|
||||
|
||||
// Bind it to both IViewManager and to itself, so that people can get it with Container.Get<ViewManager>()
|
||||
builder.Bind<IViewManager>().And<ViewManager>().To<ViewManager>().InSingletonScope().AsWeakBinding();
|
||||
|
||||
builder.Bind<IWindowManagerConfig>().ToInstance(this).DisposeWithContainer(false).AsWeakBinding();
|
||||
builder.Bind<IWindowManager>().To<WindowManager>().InSingletonScope().AsWeakBinding();
|
||||
builder.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope().AsWeakBinding();
|
||||
builder.Bind<IMessageBoxViewModel>().To<MessageBoxViewModel>().AsWeakBinding();
|
||||
// Stylet's assembly isn't added to the container, so add this explicitly
|
||||
builder.Bind<MessageBoxView>().ToSelf();
|
||||
|
||||
builder.Autobind();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to add your own types to the IoC container.
|
||||
/// </summary>
|
||||
/// <param name="builder">StyletIoC builder to use to configure the container</param>
|
||||
protected virtual void ConfigureIoC(IStyletIoCBuilder builder) { }
|
||||
|
||||
/// <summary>
|
||||
/// Given a type, use the IoC container to fetch an instance of it
|
||||
/// </summary>
|
||||
/// <param name="type">Type to fetch</param>
|
||||
/// <returns>Fetched instance</returns>
|
||||
public override object GetInstance(Type type)
|
||||
{
|
||||
return this.Container.Get(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
// Dispose the container last
|
||||
if (this.Container != null)
|
||||
this.Container.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
|
@ -42,11 +44,12 @@ namespace Stylet.Xaml
|
|||
protected readonly ActionUnavailableBehaviour ActionNonExistentBehaviour;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object on which methods will be invokced
|
||||
/// Gets the object on which methods will be invoked
|
||||
/// </summary>
|
||||
public object Target
|
||||
{
|
||||
get { return this.GetValue(targetProperty); }
|
||||
private set { this.SetValue(targetProperty, value); }
|
||||
}
|
||||
|
||||
private static readonly DependencyProperty targetProperty =
|
||||
|
@ -56,7 +59,7 @@ namespace Stylet.Xaml
|
|||
}));
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="ActionBase"/> class
|
||||
/// Initialises a new instance of the <see cref="ActionBase"/> class to use <see cref="View.ActionTargetProperty"/> to get the target
|
||||
/// </summary>
|
||||
/// <param name="subject">View to grab the View.ActionTarget from</param>
|
||||
/// <param name="backupSubject">Backup subject to use if no ActionTarget could be retrieved from the subject</param>
|
||||
|
@ -65,12 +68,9 @@ namespace Stylet.Xaml
|
|||
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
|
||||
/// <param name="logger">Logger to use</param>
|
||||
public ActionBase(DependencyObject subject, DependencyObject backupSubject, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour, ILogger logger)
|
||||
: this(methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{
|
||||
this.Subject = subject;
|
||||
this.MethodName = methodName;
|
||||
this.TargetNullBehaviour = targetNullBehaviour;
|
||||
this.ActionNonExistentBehaviour = actionNonExistentBehaviour;
|
||||
this.logger = logger;
|
||||
|
||||
// If a 'backupSubject' was given, bind both that and 'subject' to this.Target (with a converter which picks the first
|
||||
// one that isn't View.InitialActionTarget). If it wasn't given, just bind 'subject'.
|
||||
|
@ -101,6 +101,31 @@ namespace Stylet.Xaml
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="ActionBase"/> class to use an explicit target
|
||||
/// </summary>
|
||||
/// <param name="target">Target to find the method on</param>
|
||||
/// <param name="methodName">Method name. the MyMethod in Buttom Command="{s:Action MyMethod}".</param>
|
||||
/// <param name="targetNullBehaviour">Behaviour for it the relevant View.ActionTarget is null</param>
|
||||
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
|
||||
/// <param name="logger">Logger to use</param>
|
||||
public ActionBase(object target, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour, ILogger logger)
|
||||
: this(methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
|
||||
this.Target = target;
|
||||
}
|
||||
|
||||
private ActionBase(string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour, ILogger logger)
|
||||
{
|
||||
this.MethodName = methodName ?? throw new ArgumentNullException(nameof(methodName));
|
||||
this.TargetNullBehaviour = targetNullBehaviour;
|
||||
this.ActionNonExistentBehaviour = actionNonExistentBehaviour;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private void UpdateActionTarget(object oldTarget, object newTarget)
|
||||
{
|
||||
MethodInfo targetMethodInfo = null;
|
||||
|
@ -128,13 +153,22 @@ namespace Stylet.Xaml
|
|||
}
|
||||
else
|
||||
{
|
||||
var newTargetType = newTarget.GetType();
|
||||
BindingFlags bindingFlags;
|
||||
if (newTarget is Type newTargetType)
|
||||
{
|
||||
bindingFlags = BindingFlags.Public | BindingFlags.Static;
|
||||
}
|
||||
else
|
||||
{
|
||||
newTargetType = newTarget.GetType();
|
||||
bindingFlags = BindingFlags.Public | BindingFlags.Instance;
|
||||
}
|
||||
try
|
||||
{
|
||||
targetMethodInfo = newTargetType.GetMethod(this.MethodName);
|
||||
targetMethodInfo = newTargetType.GetMethod(this.MethodName, bindingFlags);
|
||||
|
||||
if (targetMethodInfo == null)
|
||||
this.logger.Warn("Unable to find method {0} on {1}", this.MethodName, newTargetType.Name);
|
||||
this.logger.Warn("Unable to find{0} method {1} on {2}", newTarget is Type ? " static" : "", this.MethodName, newTargetType.Name);
|
||||
else
|
||||
this.AssertTargetMethodInfo(targetMethodInfo, newTargetType);
|
||||
}
|
||||
|
@ -156,19 +190,19 @@ namespace Stylet.Xaml
|
|||
/// </summary>
|
||||
/// <param name="targetMethodInfo">MethodInfo of method on new target</param>
|
||||
/// <param name="newTargetType">Type of new target</param>
|
||||
protected internal abstract void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType);
|
||||
private protected abstract void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a new target is set, after all other action has been taken
|
||||
/// </summary>
|
||||
/// <param name="oldTarget">Previous target</param>
|
||||
/// <param name="newTarget">New target</param>
|
||||
protected internal virtual void OnTargetChanged(object oldTarget, object newTarget) { }
|
||||
private protected virtual void OnTargetChanged(object oldTarget, object newTarget) { }
|
||||
|
||||
/// <summary>
|
||||
/// Assert that the target is not View.InitialActionTarget
|
||||
/// </summary>
|
||||
protected internal void AssertTargetSet()
|
||||
private protected void AssertTargetSet()
|
||||
{
|
||||
// If we've made it this far and the target is still the default, then something's wrong
|
||||
// Make sure they know
|
||||
|
@ -183,7 +217,7 @@ namespace Stylet.Xaml
|
|||
|
||||
if (this.TargetMethodInfo == null && this.ActionNonExistentBehaviour == ActionUnavailableBehaviour.Throw)
|
||||
{
|
||||
var ex = new ActionNotFoundException(String.Format("Unable to find method {0} on target {1}", this.MethodName, this.Target.GetType().Name));
|
||||
var ex = new ActionNotFoundException(String.Format("Unable to find method {0} on {1}", this.MethodName, this.TargetName()));
|
||||
this.logger.Error(ex);
|
||||
throw ex;
|
||||
}
|
||||
|
@ -193,22 +227,37 @@ namespace Stylet.Xaml
|
|||
/// Invoke the target method with the given parameters
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters to pass to the target method</param>
|
||||
protected internal void InvokeTargetMethod(object[] parameters)
|
||||
private protected void InvokeTargetMethod(object[] parameters)
|
||||
{
|
||||
this.logger.Info("Invoking method {0} on target {1} with parameters ({2})", this.MethodName, this.Target, parameters == null ? "none" : String.Join(", ", parameters));
|
||||
this.logger.Info("Invoking method {0} on {1} with parameters ({2})", this.MethodName, this.TargetName(), parameters == null ? "none" : String.Join(", ", parameters));
|
||||
|
||||
try
|
||||
{
|
||||
this.TargetMethodInfo.Invoke(this.Target, parameters);
|
||||
var target = this.TargetMethodInfo.IsStatic ? null : this.Target;
|
||||
var result = this.TargetMethodInfo.Invoke(target, parameters);
|
||||
// Be nice and make sure that any exceptions get rethrown
|
||||
if (result is Task task)
|
||||
{
|
||||
AwaitTask(task);
|
||||
}
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
// Be nice and unwrap this for them
|
||||
// They want a stack track for their VM method, not us
|
||||
this.logger.Error(e.InnerException, String.Format("Failed to invoke method {0} on target {1} with parameters ({2})", this.MethodName, this.Target, parameters == null ? "none" : String.Join(", ", parameters)));
|
||||
this.logger.Error(e.InnerException, String.Format("Failed to invoke method {0} on {1} with parameters ({2})", this.MethodName, this.TargetName(), parameters == null ? "none" : String.Join(", ", parameters)));
|
||||
// http://stackoverflow.com/a/17091351/1086121
|
||||
ExceptionDispatchInfo.Capture(e.InnerException).Throw();
|
||||
}
|
||||
|
||||
async void AwaitTask(Task t) => await t;
|
||||
}
|
||||
|
||||
private string TargetName()
|
||||
{
|
||||
return this.Target is Type t
|
||||
? $"static target {t.Name}"
|
||||
: $"target {this.Target.GetType().Name}";
|
||||
}
|
||||
|
||||
private class MultiBindingToActionTargetConverter : IMultiValueConverter
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace Stylet.Xaml
|
|||
[ConstructorArgument("method")]
|
||||
public string Method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a target to override that set with View.ActionTarget
|
||||
/// </summary>
|
||||
public object Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the behaviour if the View.ActionTarget is nulil
|
||||
/// </summary>
|
||||
|
@ -101,15 +106,13 @@ namespace Stylet.Xaml
|
|||
throw new InvalidOperationException("Method has not been set");
|
||||
|
||||
var valueService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
|
||||
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
|
||||
var rootObject = rootObjectProvider?.RootObject as DependencyObject;
|
||||
|
||||
switch (valueService.TargetObject)
|
||||
{
|
||||
case DependencyObject targetObject:
|
||||
return this.HandleDependencyObject(valueService, targetObject, rootObject);
|
||||
return this.HandleDependencyObject(serviceProvider, valueService, targetObject);
|
||||
case CommandBinding commandBinding:
|
||||
return this.HandleCommandBinding(rootObject, ((EventInfo)valueService.TargetProperty).EventHandlerType);
|
||||
return this.CreateEventAction(serviceProvider, null, ((EventInfo)valueService.TargetProperty).EventHandlerType, isCommandBinding: true);
|
||||
default:
|
||||
// Seems this is the case when we're in a template. We'll get called again properly in a second.
|
||||
// http://social.msdn.microsoft.com/Forums/vstudio/en-US/a9ead3d5-a4e4-4f9c-b507-b7a7d530c6a9/gaining-access-to-target-object-instead-of-shareddp-in-custom-markupextensions-providevalue-method?forum=wpf
|
||||
|
@ -117,39 +120,66 @@ namespace Stylet.Xaml
|
|||
}
|
||||
}
|
||||
|
||||
private object HandleDependencyObject(IProvideValueTarget valueService, DependencyObject targetObject, DependencyObject rootObject)
|
||||
private object HandleDependencyObject(IServiceProvider serviceProvider, IProvideValueTarget valueService, DependencyObject targetObject)
|
||||
{
|
||||
switch (valueService.TargetProperty)
|
||||
{
|
||||
case DependencyProperty dependencyProperty when dependencyProperty.PropertyType == typeof(ICommand):
|
||||
// If they're in design mode and haven't set View.ActionTarget, default to looking sensible
|
||||
return new CommandAction(targetObject, rootObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
return this.CreateCommandAction(serviceProvider, targetObject);
|
||||
case EventInfo eventInfo:
|
||||
{
|
||||
var ec = new EventAction(targetObject, rootObject, eventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
return this.CreateEventAction(serviceProvider, targetObject, eventInfo.EventHandlerType);
|
||||
case MethodInfo methodInfo: // For attached events
|
||||
{
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (parameters.Length == 2 && typeof(Delegate).IsAssignableFrom(parameters[1].ParameterType))
|
||||
{
|
||||
var ec = new EventAction(targetObject, rootObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (parameters.Length == 2 && typeof(Delegate).IsAssignableFrom(parameters[1].ParameterType))
|
||||
{
|
||||
return this.CreateEventAction(serviceProvider, targetObject, parameters[1].ParameterType);
|
||||
}
|
||||
throw new ArgumentException("Action used with an attached event (or something similar) which didn't follow the normal pattern");
|
||||
}
|
||||
throw new ArgumentException("Action used with an attached event (or something similar) which didn't follow the normal pattern");
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException("Can only use ActionExtension with a Command property or an event handler");
|
||||
}
|
||||
}
|
||||
|
||||
private object HandleCommandBinding(DependencyObject rootObject, Type propertyType)
|
||||
private ICommand CreateCommandAction(IServiceProvider serviceProvider, DependencyObject targetObject)
|
||||
{
|
||||
if (rootObject == null)
|
||||
throw new InvalidOperationException("Action may only be used with CommandBinding from a XAML view (unable to retrieve IRootObjectProvider.RootObject)");
|
||||
if (this.Target == null)
|
||||
{
|
||||
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
|
||||
var rootObject = rootObjectProvider?.RootObject as DependencyObject;
|
||||
return new CommandAction(targetObject, rootObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CommandAction(this.Target, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
}
|
||||
}
|
||||
|
||||
private Delegate CreateEventAction(IServiceProvider serviceProvider, DependencyObject targetObject, Type eventType, bool isCommandBinding = false)
|
||||
{
|
||||
EventAction ec;
|
||||
if (this.Target == null)
|
||||
{
|
||||
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
|
||||
var rootObject = rootObjectProvider?.RootObject as DependencyObject;
|
||||
if (isCommandBinding)
|
||||
{
|
||||
if (rootObject == null)
|
||||
throw new InvalidOperationException("Action may only be used with CommandBinding from a XAML view (unable to retrieve IRootObjectProvider.RootObject)");
|
||||
ec = new EventAction(rootObject, null, eventType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = new EventAction(targetObject, rootObject, eventType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = new EventAction(this.Target, eventType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
}
|
||||
|
||||
var ec = new EventAction(rootObject, null, propertyType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Stylet.Xaml
|
|||
private Func<bool> guardPropertyGetter;
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="CommandAction"/> class
|
||||
/// Initialises a new instance of the <see cref="CommandAction"/> class to use <see cref="View.ActionTargetProperty"/> to get the target
|
||||
/// </summary>
|
||||
/// <param name="subject">View to grab the View.ActionTarget from</param>
|
||||
/// <param name="backupSubject">Backup subject to use if no ActionTarget could be retrieved from the subject</param>
|
||||
|
@ -37,6 +37,17 @@ namespace Stylet.Xaml
|
|||
: base(subject, backupSubject, methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="CommandAction"/> class to use an explicit target
|
||||
/// </summary>
|
||||
/// <param name="target">Target to find the method on</param>
|
||||
/// <param name="methodName">Method name. the MyMethod in Buttom Command="{s:Action MyMethod}".</param>
|
||||
/// <param name="targetNullBehaviour">Behaviour for it the relevant View.ActionTarget is null</param>
|
||||
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
|
||||
public CommandAction(object target, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
|
||||
: base(target, methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{ }
|
||||
|
||||
private string GuardName
|
||||
{
|
||||
get { return "Can" + this.MethodName; }
|
||||
|
@ -47,7 +58,7 @@ namespace Stylet.Xaml
|
|||
/// </summary>
|
||||
/// <param name="targetMethodInfo">MethodInfo of method on new target</param>
|
||||
/// <param name="newTargetType">Type of new target</param>
|
||||
protected internal override void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType)
|
||||
private protected override void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType)
|
||||
{
|
||||
var methodParameters = targetMethodInfo.GetParameters();
|
||||
if (methodParameters.Length > 1)
|
||||
|
@ -63,34 +74,33 @@ namespace Stylet.Xaml
|
|||
/// </summary>
|
||||
/// <param name="oldTarget">Previous target</param>
|
||||
/// <param name="newTarget">New target</param>
|
||||
protected internal override void OnTargetChanged(object oldTarget, object newTarget)
|
||||
private protected override void OnTargetChanged(object oldTarget, object newTarget)
|
||||
{
|
||||
var oldInpc = oldTarget as INotifyPropertyChanged;
|
||||
if (oldInpc != null)
|
||||
if (oldTarget is INotifyPropertyChanged oldInpc)
|
||||
PropertyChangedEventManager.RemoveHandler(oldInpc, this.PropertyChangedHandler, this.GuardName);
|
||||
|
||||
this.guardPropertyGetter = null;
|
||||
|
||||
var inpc = newTarget as INotifyPropertyChanged;
|
||||
if (inpc != null)
|
||||
var guardPropertyInfo = newTarget?.GetType().GetProperty(this.GuardName);
|
||||
if (guardPropertyInfo != null)
|
||||
{
|
||||
var guardPropertyInfo = newTarget.GetType().GetProperty(this.GuardName);
|
||||
if (guardPropertyInfo != null)
|
||||
if (guardPropertyInfo.PropertyType == typeof(bool))
|
||||
{
|
||||
if (guardPropertyInfo.PropertyType == typeof(bool))
|
||||
{
|
||||
var targetExpression = Expressions.Expression.Constant(newTarget);
|
||||
var propertyAccess = Expressions.Expression.Property(targetExpression, guardPropertyInfo);
|
||||
this.guardPropertyGetter = Expressions.Expression.Lambda<Func<bool>>(propertyAccess).Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Found guard property {0} for action {1} on target {2}, but its return type wasn't bool. Therefore, ignoring", this.GuardName, this.MethodName, newTarget);
|
||||
}
|
||||
var targetExpression = Expressions.Expression.Constant(newTarget);
|
||||
var propertyAccess = Expressions.Expression.Property(targetExpression, guardPropertyInfo);
|
||||
this.guardPropertyGetter = Expressions.Expression.Lambda<Func<bool>>(propertyAccess).Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Found guard property {0} for action {1} on target {2}, but its return type wasn't bool. Therefore, ignoring", this.GuardName, this.MethodName, newTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.guardPropertyGetter != null)
|
||||
if (this.guardPropertyGetter != null)
|
||||
{
|
||||
if (newTarget is INotifyPropertyChanged inpc)
|
||||
PropertyChangedEventManager.AddHandler(inpc, this.PropertyChangedHandler, this.GuardName);
|
||||
else
|
||||
logger.Warn("Found guard property {0} for action {1} on target {2}, but the target doesn't implement INotifyPropertyChanged, so changes won't be observed", this.GuardName, this.MethodName, newTarget);
|
||||
}
|
||||
|
||||
this.UpdateCanExecute();
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Stylet.Xaml
|
|||
private readonly Type eventHandlerType;
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="EventAction"/> class
|
||||
/// Initialises a new instance of the <see cref="EventAction"/> classto use <see cref="View.ActionTargetProperty"/> to get the target
|
||||
/// </summary>
|
||||
/// <param name="subject">View whose View.ActionTarget we watch</param>
|
||||
/// <param name="backupSubject">Backup subject to use if no ActionTarget could be retrieved from the subject</param>
|
||||
|
@ -33,13 +33,32 @@ namespace Stylet.Xaml
|
|||
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
|
||||
public EventAction(DependencyObject subject, DependencyObject backupSubject, Type eventHandlerType, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
|
||||
: base(subject, backupSubject, methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{
|
||||
AssertBehaviours(targetNullBehaviour, actionNonExistentBehaviour);
|
||||
this.eventHandlerType = eventHandlerType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the <see cref="EventAction"/> class to use an explicit target
|
||||
/// </summary>
|
||||
/// <param name="target">Target to find the method on</param>
|
||||
/// <param name="eventHandlerType">Type of event handler we're returning a delegate for</param>
|
||||
/// <param name="methodName">The MyMethod in {s:Action MyMethod}, this is what we call when the event's fired</param>
|
||||
/// <param name="targetNullBehaviour">Behaviour for it the relevant View.ActionTarget is null</param>
|
||||
/// <param name="actionNonExistentBehaviour">Behaviour for if the action doesn't exist on the View.ActionTarget</param>
|
||||
public EventAction(object target, Type eventHandlerType, string methodName, ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
|
||||
: base(target, methodName, targetNullBehaviour, actionNonExistentBehaviour, logger)
|
||||
{
|
||||
AssertBehaviours(targetNullBehaviour, actionNonExistentBehaviour);
|
||||
this.eventHandlerType = eventHandlerType;
|
||||
}
|
||||
|
||||
private static void AssertBehaviours(ActionUnavailableBehaviour targetNullBehaviour, ActionUnavailableBehaviour actionNonExistentBehaviour)
|
||||
{
|
||||
if (targetNullBehaviour == ActionUnavailableBehaviour.Disable)
|
||||
throw new ArgumentException("Setting NullTarget = Disable is unsupported when used on an Event");
|
||||
if (actionNonExistentBehaviour == ActionUnavailableBehaviour.Disable)
|
||||
throw new ArgumentException("Setting ActionNotFound = Disable is unsupported when used on an Event");
|
||||
|
||||
this.eventHandlerType = eventHandlerType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -47,14 +66,14 @@ namespace Stylet.Xaml
|
|||
/// </summary>
|
||||
/// <param name="targetMethodInfo">MethodInfo of method on new target</param>
|
||||
/// <param name="newTargetType">Type of new target</param>
|
||||
protected internal override void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType)
|
||||
private protected override void AssertTargetMethodInfo(MethodInfo targetMethodInfo, Type newTargetType)
|
||||
{
|
||||
var methodParameters = targetMethodInfo.GetParameters();
|
||||
if (!(methodParameters.Length == 0 ||
|
||||
(methodParameters.Length == 1 && (typeof(EventArgs).IsAssignableFrom(methodParameters[0].ParameterType) || methodParameters[0].ParameterType == typeof(DependencyPropertyChangedEventArgs))) ||
|
||||
(methodParameters.Length == 2 && (typeof(EventArgs).IsAssignableFrom(methodParameters[1].ParameterType) || methodParameters[1].ParameterType == typeof(DependencyPropertyChangedEventArgs)))))
|
||||
{
|
||||
var e = new ActionSignatureInvalidException(String.Format("Method {0} on {1} must have the signatures void Method(), void Method(EventArgsOrSubClass e), or void Method(object sender, EventArgsOrSubClass e)", this.MethodName, newTargetType.Name));
|
||||
var e = new ActionSignatureInvalidException(String.Format("Method {0} on {1} must have the signatures Method(), Method(EventArgsOrSubClass e), or Method(object sender, EventArgsOrSubClass e)", this.MethodName, newTargetType.Name));
|
||||
logger.Error(e);
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -126,6 +126,19 @@ namespace StyletUnitTests
|
|||
|
||||
Assert.Throws<InvalidOperationException>(() => this.actionExtension.ProvideValue(this.serviceProvider.Object));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OverridesTargetIfSetCommand()
|
||||
{
|
||||
var target = new object();
|
||||
this.actionExtension.Target = target;
|
||||
|
||||
this.provideValueTarget.Setup(x => x.TargetProperty).Returns(Button.CommandProperty);
|
||||
var cmd = (CommandAction)this.actionExtension.ProvideValue(this.serviceProvider.Object);
|
||||
Assert.AreSame(target, cmd.Target);
|
||||
}
|
||||
|
||||
// Can't really test Target on EventAction. Oh well.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using Stylet;
|
||||
using Stylet.Xaml;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace StyletUnitTests
|
||||
|
@ -23,8 +24,11 @@ namespace StyletUnitTests
|
|||
get { return this._canDoSomethingWithGuard; }
|
||||
set { SetAndNotify(ref this._canDoSomethingWithGuard, value); }
|
||||
}
|
||||
|
||||
public bool DoSomethingWithGuardCalled;
|
||||
public void DoSomethingWithGuard()
|
||||
{
|
||||
this.DoSomethingWithGuardCalled = true;
|
||||
}
|
||||
|
||||
public object DoSomethingArgument;
|
||||
|
@ -62,6 +66,18 @@ namespace StyletUnitTests
|
|||
{
|
||||
}
|
||||
|
||||
private class TargetWithoutInpc
|
||||
{
|
||||
public bool CanDoSomething => false;
|
||||
public void DoSomething() { }
|
||||
}
|
||||
|
||||
public class StaticTarget
|
||||
{
|
||||
public static bool DidSomething;
|
||||
public static void DoSomething() => DidSomething = true;
|
||||
}
|
||||
|
||||
private DependencyObject subject;
|
||||
private Target target;
|
||||
|
||||
|
@ -71,6 +87,7 @@ namespace StyletUnitTests
|
|||
this.target = new Target();
|
||||
this.subject = new DependencyObject();
|
||||
View.SetActionTarget(this.subject, this.target);
|
||||
StaticTarget.DidSomething = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -171,6 +188,18 @@ namespace StyletUnitTests
|
|||
Assert.True(eventRaised);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FetchesGuardPropertyWhenTargetDoesNotImplementInpc()
|
||||
{
|
||||
var target = new TargetWithoutInpc();
|
||||
var cmd = new CommandAction(this.subject, null, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
bool eventRaised = false;
|
||||
cmd.CanExecuteChanged += (o, e) => eventRaised = true;
|
||||
View.SetActionTarget(this.subject, target);
|
||||
Assert.True(eventRaised);
|
||||
Assert.False(cmd.CanExecute(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RaisesEventWhenTargetChanges()
|
||||
{
|
||||
|
@ -297,5 +326,29 @@ namespace StyletUnitTests
|
|||
cmd.Execute(null);
|
||||
Assert.IsTrue(this.target.DoSomethingCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SupportsStaticTargets()
|
||||
{
|
||||
var cmd = new CommandAction(this.subject, null, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
View.SetActionTarget(this.subject, typeof(StaticTarget));
|
||||
|
||||
Assert.True(cmd.CanExecute(null));
|
||||
cmd.Execute(null);
|
||||
Assert.True(StaticTarget.DidSomething);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UsesExplicitTarget()
|
||||
{
|
||||
var cmd = new CommandAction(this.target, "DoSomethingWithGuard", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
|
||||
Assert.False(cmd.CanExecute(null));
|
||||
this.target.CanDoSomethingWithGuard = true;
|
||||
Assert.True(cmd.CanExecute(null));
|
||||
|
||||
cmd.Execute(null);
|
||||
Assert.True(this.target.DoSomethingWithGuardCalled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,12 @@ namespace StyletUnitTests
|
|||
{
|
||||
}
|
||||
|
||||
public class StaticTarget
|
||||
{
|
||||
public static bool DidSomething;
|
||||
public static void DoSomething() => DidSomething = true;
|
||||
}
|
||||
|
||||
private DependencyObject subject;
|
||||
private Target target;
|
||||
private EventInfo eventInfo;
|
||||
|
@ -87,6 +93,7 @@ namespace StyletUnitTests
|
|||
this.eventInfo = typeof(Subject).GetEvent("SimpleEventHandler");
|
||||
this.dependencyChangedEventInfo = typeof(Subject).GetEvent("DependencyChangedEventHandler");
|
||||
View.SetActionTarget(this.subject, this.target);
|
||||
StaticTarget.DidSomething = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -269,13 +276,31 @@ namespace StyletUnitTests
|
|||
{
|
||||
var view = new DependencyObject();
|
||||
var backupView = new DependencyObject();
|
||||
var cmd = new CommandAction(view, backupView, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
var cmd = new EventAction(view, backupView, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
|
||||
View.SetActionTarget(backupView, this.target);
|
||||
view.SetValue(FrameworkElement.DataContextProperty, this.target);
|
||||
|
||||
cmd.Execute(null);
|
||||
cmd.GetDelegate().DynamicInvoke(null, null);
|
||||
Assert.IsTrue(this.target.DoSomethingCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SupportsStaticTargets()
|
||||
{
|
||||
var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
View.SetActionTarget(this.subject, typeof(StaticTarget));
|
||||
|
||||
cmd.GetDelegate().DynamicInvoke(null, null);
|
||||
Assert.True(StaticTarget.DidSomething);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UsesExplicitTarget()
|
||||
{
|
||||
var cmd = new EventAction(this.target, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
|
||||
cmd.GetDelegate().DynamicInvoke(null, null);
|
||||
Assert.True(this.target.DoSomethingCalled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/2.1.2">
|
||||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net5.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net5.0-windows</TargetFrameworks>
|
||||
|
||||
<UseWpf>true</UseWpf>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
Loading…
Reference in New Issue