diff --git a/samples/features/Features.Avalonia/.gitignore b/samples/features/Features.Avalonia/.gitignore new file mode 100644 index 000000000..8afdcb635 --- /dev/null +++ b/samples/features/Features.Avalonia/.gitignore @@ -0,0 +1,454 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/samples/features/Features.Avalonia/App.axaml b/samples/features/Features.Avalonia/App.axaml new file mode 100644 index 000000000..6c02be0d2 --- /dev/null +++ b/samples/features/Features.Avalonia/App.axaml @@ -0,0 +1,7 @@ + + + + + diff --git a/samples/features/Features.Avalonia/App.axaml.cs b/samples/features/Features.Avalonia/App.axaml.cs new file mode 100644 index 000000000..e42a7fa2c --- /dev/null +++ b/samples/features/Features.Avalonia/App.axaml.cs @@ -0,0 +1,20 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; + +namespace Features.Avalonia +{ + public partial class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + base.OnFrameworkInitializationCompleted(); + new Bootstrapper(); + } + } +} diff --git a/samples/features/Features.Avalonia/Bootstrapper.cs b/samples/features/Features.Avalonia/Bootstrapper.cs new file mode 100644 index 000000000..c7bc6e297 --- /dev/null +++ b/samples/features/Features.Avalonia/Bootstrapper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows; +using Caliburn.Micro; +using Features.CrossPlatform.ViewModels; + + +namespace Features.Avalonia +{ + public class Bootstrapper : BootstrapperBase + { + private readonly SimpleContainer _container; + + public Bootstrapper() + { + LogManager.GetLog = type => new DebugLog(type); + _container = new SimpleContainer(); + _container.Instance(_container); + + Initialize(); + + (DisplayRootViewFor()).ConfigureAwait(false); + } + + protected override void Configure() + { + _container + .Singleton() + .Singleton(); + + _container + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest() + .PerRequest(); + } + + + protected override object GetInstance(Type service, string key) + { + return _container.GetInstance(service, key); + } + + protected override IEnumerable GetAllInstances(Type service) + { + return _container.GetAllInstances(service); + } + + protected override void BuildUp(object instance) + { + _container.BuildUp(instance); + } + + + } +} diff --git a/samples/features/Features.Avalonia/Features.Avalonia.csproj b/samples/features/Features.Avalonia/Features.Avalonia.csproj new file mode 100644 index 000000000..a7fdbd8c3 --- /dev/null +++ b/samples/features/Features.Avalonia/Features.Avalonia.csproj @@ -0,0 +1,54 @@ + + + WinExe + net8.0 + enable + 10 + false + + + AVALONIA + + + + AVALONIA + + + + + + + + + + + + + + + + + + + + + ..\..\..\bin\Caliburn.Micro.Avalonia\Release\net8.0\Caliburn.Micro.Avalonia.dll + + + ..\..\..\bin\Caliburn.Micro.Avalonia\Release\net8.0\Caliburn.Micro.Core.dll + + + + + + + ActionsView.axaml + + + BindingsView.axaml + + + + + + diff --git a/samples/features/Features.Avalonia/Lipsum.cs b/samples/features/Features.Avalonia/Lipsum.cs new file mode 100644 index 000000000..b6d177793 --- /dev/null +++ b/samples/features/Features.Avalonia/Lipsum.cs @@ -0,0 +1,15 @@ +using System; + +namespace Features.Avalonia +{ + public static class Lipsum + { + private const string Base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ullamcorper ligula quis nisl varius, vitae tincidunt libero dapibus. Nunc vel nunc elit. Etiam aliquet nec ligula eget pretium. Ut non arcu sem. Fusce et auctor dui. Mauris in lorem sit amet massa varius finibus et at metus. Aliquam non mi non justo malesuada suscipit. Etiam tincidunt ullamcorper sodales. Suspendisse potenti. Etiam ut fringilla risus. Cras varius neque metus, ac laoreet mauris commodo a."; + private static readonly Random Random = new Random(); + + public static string Get(int? length = null) + { + return Base.Substring(0, Random.Next(length ?? Base.Length)); + } + } +} diff --git a/samples/features/Features.Avalonia/Messages/SimpleMessage.cs b/samples/features/Features.Avalonia/Messages/SimpleMessage.cs new file mode 100644 index 000000000..ef5cbdf40 --- /dev/null +++ b/samples/features/Features.Avalonia/Messages/SimpleMessage.cs @@ -0,0 +1,14 @@ +using System; + +namespace Features.Avalonia.Messages +{ + public class SimpleMessage + { + public SimpleMessage(string text) + { + Text = text; + } + + public string Text { get; } + } +} diff --git a/samples/features/Features.Avalonia/Program.cs b/samples/features/Features.Avalonia/Program.cs new file mode 100644 index 000000000..61f930bc2 --- /dev/null +++ b/samples/features/Features.Avalonia/Program.cs @@ -0,0 +1,22 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using System; + +namespace Features.Avalonia +{ + internal class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .LogToTrace(); + } +} diff --git a/samples/features/Features.Avalonia/Results/MessageDialogResult.cs b/samples/features/Features.Avalonia/Results/MessageDialogResult.cs new file mode 100644 index 000000000..075bf25a6 --- /dev/null +++ b/samples/features/Features.Avalonia/Results/MessageDialogResult.cs @@ -0,0 +1,27 @@ +using Caliburn.Micro; +using MsBox.Avalonia; + + +namespace Features.Avalonia.Results +{ + public class MessageDialogResult : ResultBase + { + private readonly string content; + private readonly string title; + + public MessageDialogResult(string content, string title) + { + this.content = content; + this.title = title; + } + + public override async void Execute(CoroutineExecutionContext context) + { + var dialog = MessageBoxManager + .GetMessageBoxStandard(title, content); + + await dialog.ShowAsync(); + OnCompleted(); + } + } +} diff --git a/samples/features/Features.Avalonia/Results/ResultBase.cs b/samples/features/Features.Avalonia/Results/ResultBase.cs new file mode 100644 index 000000000..c760606d5 --- /dev/null +++ b/samples/features/Features.Avalonia/Results/ResultBase.cs @@ -0,0 +1,38 @@ +using System; +using Caliburn.Micro; + +namespace Features.Avalonia.Results +{ + public abstract class ResultBase : IResult + { + public abstract void Execute(CoroutineExecutionContext context); + + public event EventHandler Completed = delegate { }; + + protected virtual void OnCompleted() + { + OnCompleted(new ResultCompletionEventArgs()); + } + + protected virtual void OnError(Exception error) + { + OnCompleted(new ResultCompletionEventArgs + { + Error = error + }); + } + + protected virtual void OnCancelled() + { + OnCompleted(new ResultCompletionEventArgs + { + WasCancelled = true + }); + } + + protected virtual void OnCompleted(ResultCompletionEventArgs e) + { + Caliburn.Micro.Execute.OnUIThread(() => Completed(this, e)); + } + } +} diff --git a/samples/features/Features.Avalonia/Results/VisualStateResult.cs b/samples/features/Features.Avalonia/Results/VisualStateResult.cs new file mode 100644 index 000000000..59fd747a9 --- /dev/null +++ b/samples/features/Features.Avalonia/Results/VisualStateResult.cs @@ -0,0 +1,33 @@ +using Avalonia.Controls; +using Caliburn.Micro; + +namespace Features.Avalonia.Results +{ + public class VisualStateResult : ResultBase + { + public VisualStateResult(string stateName, bool useTransitions = true) + { + StateName = stateName; + UseTransitions = useTransitions; + } + + public string StateName { get; } + + public bool UseTransitions { get; } + + public override void Execute(CoroutineExecutionContext context) + { + + if (!(context.View is Control)) + throw new System.InvalidOperationException("View must be a Control to use VisualStateResult"); + + var view = (Control)context.View; + view.Classes.Clear(); + view.Classes.Add(StateName); + OnCompleted(); + } + + + } +} + diff --git a/samples/features/Features.Avalonia/TaskHelper.cs b/samples/features/Features.Avalonia/TaskHelper.cs new file mode 100644 index 000000000..0acf32417 --- /dev/null +++ b/samples/features/Features.Avalonia/TaskHelper.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Features.Avalonia +{ + /// + /// Helper class to manage differences in the Task libraries between versions + /// + public static class TaskHelper + { + + public static Task FromResult(T result) => Task.FromResult(result); + public static Task Delay(int milliseconds) => Task.Delay(milliseconds); + + } +} diff --git a/samples/features/Features.Avalonia/ViewModels/ShellViewModel.cs b/samples/features/Features.Avalonia/ViewModels/ShellViewModel.cs new file mode 100644 index 000000000..420dd0109 --- /dev/null +++ b/samples/features/Features.Avalonia/ViewModels/ShellViewModel.cs @@ -0,0 +1,50 @@ +using System.Threading; +using System.Threading.Tasks; +using Caliburn.Micro; + +namespace Features.CrossPlatform.ViewModels +{ + public class ShellViewModel : Screen, IHandle + { + private readonly IEventAggregator _eventAggregator; + private SimpleContainer _container; + private INavigationService _navigationService; + + public ShellViewModel(IEventAggregator eventAggregator, SimpleContainer container) + { + _eventAggregator = eventAggregator; + _eventAggregator.SubscribeOnPublishedThread(this); + _container = container; + } + + public async Task HandleAsync(FeatureViewModel message, CancellationToken cancellationToken) + { + await _navigationService.NavigateToViewModelAsync(message.ViewModel); + } + + protected override async Task OnInitializedAsync(CancellationToken cancellationToken) + { + await base.OnInitializedAsync(cancellationToken); + + GoHome(); + } + + public void GoHome() + { + var menuVM = _container.GetInstance(); + if (_navigationService != null) + { + _navigationService.NavigateToViewModelAsync(typeof(MenuViewModel)); + } + } + + public async void NavReady(NavigationFrame frame) + { + _navigationService = frame as INavigationService; + + _container.Instance(_navigationService); + await _navigationService.NavigateToViewModelAsync(typeof(MenuViewModel)); + } + } + +} diff --git a/samples/features/Features.Avalonia/Views/ActionsView.axaml b/samples/features/Features.Avalonia/Views/ActionsView.axaml new file mode 100644 index 000000000..5e254ad73 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/ActionsView.axaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/features/Features.Avalonia/Views/MenuView.axaml.cs b/samples/features/Features.Avalonia/Views/MenuView.axaml.cs new file mode 100644 index 000000000..89619ee85 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/MenuView.axaml.cs @@ -0,0 +1,24 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Caliburn.Micro; + +namespace Features.CrossPlatform.Views +{ + public partial class MenuView : UserControl + { + + public MenuView() + { + InitializeComponent(); + } + + + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + + } + } +} diff --git a/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml b/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml new file mode 100644 index 000000000..ad20e8ce3 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml.cs b/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml.cs new file mode 100644 index 000000000..83f5794eb --- /dev/null +++ b/samples/features/Features.Avalonia/Views/NavigationSourceView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Features.CrossPlatform.Views +{ + public partial class NavigationSourceView : UserControl + { + public NavigationSourceView() + { + InitializeComponent(); + } + } +} diff --git a/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml b/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml new file mode 100644 index 000000000..857fa254e --- /dev/null +++ b/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml.cs b/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml.cs new file mode 100644 index 000000000..1b175b34b --- /dev/null +++ b/samples/features/Features.Avalonia/Views/NavigationTargetView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Features.CrossPlatform.Views +{ + public partial class NavigationTargetView : UserControl + { + public NavigationTargetView() + { + InitializeComponent(); + } + } +} diff --git a/samples/features/Features.Avalonia/Views/ShellView.axaml b/samples/features/Features.Avalonia/Views/ShellView.axaml new file mode 100644 index 000000000..6976062fc --- /dev/null +++ b/samples/features/Features.Avalonia/Views/ShellView.axaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + diff --git a/samples/features/Features.Avalonia/Views/ShellView.axaml.cs b/samples/features/Features.Avalonia/Views/ShellView.axaml.cs new file mode 100644 index 000000000..e491619d2 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/ShellView.axaml.cs @@ -0,0 +1,26 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Features.CrossPlatform.Views +{ + public partial class ShellView : Window + { + public ShellView() + { + InitializeComponent(); +#if DEBUG + this.AttachDevTools(); +#endif + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + + } + + + } +} diff --git a/samples/features/Features.Avalonia/Views/TabView.axaml b/samples/features/Features.Avalonia/Views/TabView.axaml new file mode 100644 index 000000000..e9c774203 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/TabView.axaml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/samples/features/Features.Avalonia/Views/TabView.axaml.cs b/samples/features/Features.Avalonia/Views/TabView.axaml.cs new file mode 100644 index 000000000..122f0a319 --- /dev/null +++ b/samples/features/Features.Avalonia/Views/TabView.axaml.cs @@ -0,0 +1,21 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Features.CrossPlatform.Views +{ + public partial class TabView : UserControl + { + + + public TabView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/samples/features/Features.CrossPlatform.Shared/Results/MessageDialogResult.cs b/samples/features/Features.CrossPlatform.Shared/Results/MessageDialogResult.cs index 29e12d6e4..0185223b4 100644 --- a/samples/features/Features.CrossPlatform.Shared/Results/MessageDialogResult.cs +++ b/samples/features/Features.CrossPlatform.Shared/Results/MessageDialogResult.cs @@ -4,6 +4,9 @@ using Xamarin.Forms; #elif SILVERLIGHT || WPF using System.Windows; +#elif AVALONIA +using Avalonia.Controls; +using MsBox.Avalonia; #else using Windows.UI.Popups; #endif @@ -12,13 +15,13 @@ namespace Features.CrossPlatform.Results { public class MessageDialogResult : ResultBase { - private readonly string content; - private readonly string title; + private readonly string _content; + private readonly string _title; public MessageDialogResult(string content, string title) { - this.content = content; - this.title = title; + _content = content; + _title = title; } #if XAMARINFORMS public override async void Execute(CoroutineExecutionContext context) @@ -28,7 +31,7 @@ public override async void Execute(CoroutineExecutionContext context) var page = (Page) context.View; - await page.DisplayAlert(title, content, "Ok"); + await page.DisplayAlert(_title, _content, "Ok"); OnCompleted(); } @@ -36,14 +39,22 @@ public override async void Execute(CoroutineExecutionContext context) #elif SILVERLIGHT || WPF public override void Execute(CoroutineExecutionContext context) { - MessageBox.Show(content, title, MessageBoxButton.OK); + MessageBox.Show(_content, _title, MessageBoxButton.OK); + OnCompleted(); + } +#elif AVALONIA + public override async void Execute(CoroutineExecutionContext context) + { + var dialog = MessageBoxManager.GetMessageBoxStandard(_title, _content); + + await dialog.ShowAsync(); OnCompleted(); } #else public override async void Execute(CoroutineExecutionContext context) - { - var dialog = new MessageDialog(content, title); + { + var dialog = new MessageDialog(_content, _title); await dialog.ShowAsync(); @@ -51,4 +62,4 @@ public override async void Execute(CoroutineExecutionContext context) } #endif } -} \ No newline at end of file +} diff --git a/samples/features/Features.CrossPlatform.Shared/Results/VisualStateResult.cs b/samples/features/Features.CrossPlatform.Shared/Results/VisualStateResult.cs index 0525601f8..846992480 100644 --- a/samples/features/Features.CrossPlatform.Shared/Results/VisualStateResult.cs +++ b/samples/features/Features.CrossPlatform.Shared/Results/VisualStateResult.cs @@ -5,6 +5,8 @@ #if SILVERLIGHT || WPF using System.Windows; using System.Windows.Controls; +#elif AVALONIA +using Avalonia.Controls; #else using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -33,6 +35,13 @@ public override void Execute(CoroutineExecutionContext context) var view = (FrameworkElement) context.View; var success = VisualStateManager.GoToElementState(view, StateName, UseTransitions); +#elif AVALONIA + if (!(context.View is Control)) + throw new System.InvalidOperationException("View must be a Control to use VisualStateResult"); + + var view = (Control)context.View; + view.Classes.Clear(); + view.Classes.Add(StateName); #else if (!(context.View is Control)) throw new InvalidOperationException("View must be a Control to use VisualStateResult"); diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/ActionsViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/ActionsViewModel.cs index 63f388b6f..918717790 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/ActionsViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/ActionsViewModel.cs @@ -6,9 +6,13 @@ namespace Features.CrossPlatform.ViewModels { public class ActionsViewModel : Screen { - private string output; + private string _output; + public ActionsViewModel() + { + Output="Caliburn Micro"; + } - public void Clear() => Output = String.Empty; + public void Clear() => Output = string.Empty; public void SimpleSayHello() => Output = "Hello from Caliburn.Micro"; @@ -27,8 +31,8 @@ public Task SayGoodbyeAsync(string username) public string Output { - get { return output; } - set { Set(ref output, value); } + get { return _output; } + set { Set(ref _output, value); } } } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/BindingsViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/BindingsViewModel.cs index 7c6ee4be8..1c5077f3a 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/BindingsViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/BindingsViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Caliburn.Micro; using Features.CrossPlatform.ViewModels.Activity; @@ -6,7 +7,7 @@ namespace Features.CrossPlatform.ViewModels { public class BindingsViewModel : Screen { - private ActivityBaseViewModel selectedActivity; + private ActivityBaseViewModel _selectedActivity; public BindingsViewModel() { @@ -17,14 +18,16 @@ public BindingsViewModel() new MessageActivityViewModel(Lipsum.Get()), new PhotoActivityViewModel(Lipsum.Get()) }; + _selectedActivity = Activities.First(); + NotifyOfPropertyChange("Activities"); } public BindableCollection Activities { get; } public ActivityBaseViewModel SelectedActivity { - get { return selectedActivity; } - set { Set(ref selectedActivity, value); } + get { return _selectedActivity; } + set { Set(ref _selectedActivity, value); } } } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/CoroutineViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/CoroutineViewModel.cs index 0666aaaa3..029fe094c 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/CoroutineViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/CoroutineViewModel.cs @@ -6,22 +6,45 @@ namespace Features.CrossPlatform.ViewModels { public class CoroutineViewModel : Screen { + private bool _showProgressBar; + + public bool ShowProgressBar + { + get { return _showProgressBar; } + set + { + _showProgressBar = value; + NotifyOfPropertyChange(() => ShowProgressBar); + } + } + public IEnumerable Execute() { + ShowProgressBar = true; + #if XAMARINFORMS yield return new BusyResult(true); yield return TaskHelper.Delay(2000).AsResult(); yield return new BusyResult(false); +#elif AVALONIA + yield return new VisualStateResult("Loading"); + + yield return TaskHelper.Delay(2000).AsResult(); + + yield return new VisualStateResult("LoadingComplete"); #else yield return new VisualStateResult("ShowLoading"); yield return TaskHelper.Delay(2000).AsResult(); yield return new VisualStateResult("LoadingComplete"); + #endif yield return new MessageDialogResult("This was executed from a custom IResult, MessageDialogResult.", "IResult Coroutines"); - } + + ShowProgressBar = false; + } } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/ExecuteViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/ExecuteViewModel.cs index c33e18c40..1be403c71 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/ExecuteViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/ExecuteViewModel.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Caliburn.Micro; using Features.CrossPlatform.Views; @@ -7,12 +6,12 @@ namespace Features.CrossPlatform.ViewModels { public class ExecuteViewModel : Screen { - private bool safe; + private bool _safe; public bool Safe { - get { return safe; } - set { Set(ref safe, value); } + get { return _safe; } + set { Set(ref _safe, value); } } public void StartBackgroundWork() @@ -40,7 +39,7 @@ private void UnsafeBackgroundWork() private Task UpdateView() { - var view = (ExecuteView) GetView(); + var view = (ExecuteView)GetView(); view.UpdateView(); diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/MenuViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/MenuViewModel.cs index a5c0867b3..b1f1b8248 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/MenuViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/MenuViewModel.cs @@ -10,11 +10,11 @@ namespace Features.CrossPlatform.ViewModels { public class MenuViewModel : Screen { - private readonly INavigationService navigationService; - - public MenuViewModel(INavigationService navigationService) + private readonly INavigationService _navigationService; + private readonly IEventAggregator _eventAggregator; + public MenuViewModel(INavigationService navigationService, IEventAggregator eventAggregator) { - this.navigationService = navigationService; + _navigationService = navigationService; Features = new BindableCollection { @@ -33,13 +33,21 @@ public MenuViewModel(INavigationService navigationService) // Navigation // Window Manager }; + _eventAggregator = eventAggregator; } public BindableCollection Features { get; } - +#if AVALONIA + public async void ShowFeature(FeatureViewModel feature) + { + await _eventAggregator.PublishOnUIThreadAsync(feature); + } +#else public void ShowFeature(FeatureViewModel feature) { - navigationService.NavigateToViewModel(feature.ViewModel); + _navigationService.NavigateToViewModel(feature.ViewModel); } +#endif + } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationSourceViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationSourceViewModel.cs index c537d4f24..86f0f5892 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationSourceViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationSourceViewModel.cs @@ -15,7 +15,8 @@ public class NavigationSourceViewModel : Screen public NavigationSourceViewModel(INavigationService navigationService) { - this._navigationService = navigationService; + _navigationService = navigationService; + _text = string.Empty; } public string Text @@ -36,6 +37,7 @@ public void Navigate() .WithParam(v => v.Text, Text) .WithParam(v => v.IsNavigationEnabled, IsNavigationEnabled) .Navigate(); + } } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationTargetViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationTargetViewModel.cs index 43b5f1f44..9090b26d7 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationTargetViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/NavigationTargetViewModel.cs @@ -4,19 +4,19 @@ namespace Features.CrossPlatform.ViewModels { public class NavigationTargetViewModel : Screen { - private string text; - private bool isEnabled; + private string _text; + private bool _isEnabled; public string Text { - get { return text; } - set { Set(ref text, value); } + get { return _text; } + set { Set(ref _text, value); } } public bool IsNavigationEnabled { - get { return isEnabled; } - set { Set(ref isEnabled, value); } + get { return _isEnabled; } + set { Set(ref _isEnabled, value); } } } } diff --git a/samples/features/Features.CrossPlatform.Shared/ViewModels/TabViewModel.cs b/samples/features/Features.CrossPlatform.Shared/ViewModels/TabViewModel.cs index a9814a457..a727b2a55 100644 --- a/samples/features/Features.CrossPlatform.Shared/ViewModels/TabViewModel.cs +++ b/samples/features/Features.CrossPlatform.Shared/ViewModels/TabViewModel.cs @@ -7,7 +7,7 @@ namespace Features.CrossPlatform.ViewModels { public class TabViewModel : Screen { - private readonly Random random = new Random(); + private readonly Random _random = new Random(); public TabViewModel() { @@ -37,8 +37,8 @@ protected override Task OnDeactivateAsync(bool close, CancellationToken cancella public override async Task CanCloseAsync(CancellationToken cancellationToken = default) { - var delay = random.Next(5) + 1; - var canClose = random.Next(2) == 0; + var delay = _random.Next(5) + 1; + var canClose = _random.Next(2) == 0; Messages.Add($"Delaying {delay} seconds and allowing close: {canClose}"); diff --git a/samples/features/Features.NetCore/Features.NetCore.csproj b/samples/features/Features.NetCore/Features.NetCore.csproj index e5c457430..2fbac6b05 100644 --- a/samples/features/Features.NetCore/Features.NetCore.csproj +++ b/samples/features/Features.NetCore/Features.NetCore.csproj @@ -23,10 +23,10 @@ - ..\..\..\bin\Caliburn.Micro.Platform\release\netcoreapp3.1\Caliburn.Micro.Core.dll + ..\..\..\bin\Caliburn.Micro.Platform\debug\netcoreapp3.1\Caliburn.Micro.Core.dll - ..\..\..\bin\Caliburn.Micro.Platform\release\netcoreapp3.1\Caliburn.Micro.Platform.dll + ..\..\..\bin\Caliburn.Micro.Platform\debug\netcoreapp3.1\Caliburn.Micro.Platform.dll diff --git a/samples/features/Features.NetFive/App.config b/samples/features/Features.NetFive/App.config new file mode 100644 index 000000000..49cc43e1d --- /dev/null +++ b/samples/features/Features.NetFive/App.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/samples/features/Features.NetFive/Bootstrapper.cs b/samples/features/Features.NetFive/Bootstrapper.cs index 892b34b3e..5a794d573 100644 --- a/samples/features/Features.NetFive/Bootstrapper.cs +++ b/samples/features/Features.NetFive/Bootstrapper.cs @@ -13,6 +13,7 @@ public class Bootstrapper : BootstrapperBase public Bootstrapper() { + LogManager.GetLog = type => new DebugLog(type); Initialize(); } diff --git a/samples/features/Features.NetFive/Properties/Resources.Designer.cs b/samples/features/Features.NetFive/Properties/Resources.Designer.cs new file mode 100644 index 000000000..f6065ad47 --- /dev/null +++ b/samples/features/Features.NetFive/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Features.CrossPlatform.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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", "17.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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Features.CrossPlatform.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/samples/features/Features.NetFive/Properties/Resources.resx b/samples/features/Features.NetFive/Properties/Resources.resx new file mode 100644 index 000000000..4fdb1b6af --- /dev/null +++ b/samples/features/Features.NetFive/Properties/Resources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/features/Features.NetFive/Properties/Settings.Designer.cs b/samples/features/Features.NetFive/Properties/Settings.Designer.cs new file mode 100644 index 000000000..b251c7010 --- /dev/null +++ b/samples/features/Features.NetFive/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Features.CrossPlatform.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.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; + } + } + } +} diff --git a/samples/features/Features.NetFive/Properties/Settings.settings b/samples/features/Features.NetFive/Properties/Settings.settings new file mode 100644 index 000000000..049245f40 --- /dev/null +++ b/samples/features/Features.NetFive/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/features/Features.NetFive/Views/ActionsView.xaml b/samples/features/Features.NetFive/Views/ActionsView.xaml index 09f95e87f..8568a2910 100644 --- a/samples/features/Features.NetFive/Views/ActionsView.xaml +++ b/samples/features/Features.NetFive/Views/ActionsView.xaml @@ -1,7 +1,7 @@  - - - - - - -