diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.App.sln b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.App.sln new file mode 100644 index 00000000..b503a762 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.App.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31612.314 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Caliburn.Micro.Tutorial.Wpf", "Caliburn.Micro.Tutorial.Wpf\Caliburn.Micro.Tutorial.Wpf.csproj", "{91C89E27-E316-4117-85D0-5B7DA2AC3939}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {91C89E27-E316-4117-85D0-5B7DA2AC3939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91C89E27-E316-4117-85D0-5B7DA2AC3939}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91C89E27-E316-4117-85D0-5B7DA2AC3939}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91C89E27-E316-4117-85D0-5B7DA2AC3939}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7EFDF5AC-4D67-47F0-BA20-395AC9E897F9} + EndGlobalSection +EndGlobal diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml new file mode 100644 index 00000000..ba5ad623 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml.cs new file mode 100644 index 00000000..ebc0cc0e --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/App.xaml.cs @@ -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 Caliburn.Micro.Tutorial.Wpf + { + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/AssemblyInfo.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/AssemblyInfo.cs new file mode 100644 index 00000000..8b5504ec --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + 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) +)] diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Bootstrapper.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Bootstrapper.cs new file mode 100644 index 00000000..dc656bbc --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Bootstrapper.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System; +using System.Linq; +using System.Windows; +using Caliburn.Micro.Tutorial.Wpf.ViewModels; +using System.Diagnostics; + +namespace Caliburn.Micro.Tutorial.Wpf + { + public class Bootstrapper: BootstrapperBase + { + private readonly SimpleContainer _container = new SimpleContainer(); + + public Bootstrapper() + { + Initialize(); + StartDebugLogger(); + } + + // [Conditional("DEBUG")] You can use this conditional starting with C# 9.0 + public static void StartDebugLogger() + { + LogManager.GetLog = type => new DebugLog(type); + } + + protected override void Configure() + { + _container.Instance(_container); + _container + .Singleton() + .Singleton(); + + foreach(var assembly in SelectAssemblies()) + { + assembly.GetTypes() + .Where(type => type.IsClass) + .Where(type => type.Name.EndsWith("ViewModel")) + .ToList() + .ForEach(viewModelType => _container.RegisterPerRequest( + viewModelType, viewModelType.ToString(), viewModelType)); + } + } + + protected override async void OnStartup(object sender, StartupEventArgs e) + { + var c= IoC.Get(); + await DisplayRootViewForAsync(typeof(ShellViewModel)); + } + + 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/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Caliburn.Micro.Tutorial.Wpf.csproj b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Caliburn.Micro.Tutorial.Wpf.csproj new file mode 100644 index 00000000..c6b1d22e --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Caliburn.Micro.Tutorial.Wpf.csproj @@ -0,0 +1,13 @@ + + + + WinExe + netcoreapp3.1 + true + + + + + + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/DebugLogger.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/DebugLogger.cs new file mode 100644 index 00000000..9d046d10 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/DebugLogger.cs @@ -0,0 +1,37 @@ +using System; +using System.Diagnostics; + +namespace Caliburn.Micro.Tutorial.Wpf + { + class DebugLogger : ILog + + { + private readonly Type _type; + + public DebugLogger(Type type) + { + _type = type; + } + + public void Info(string format, params object[] args) + { + if (format.StartsWith("No bindable")) + return; + if (format.StartsWith("Action Convention Not Applied")) + return; + Debug.WriteLine("INFO: " + format, args); + } + + public void Warn(string format, params object[] args) + { + Debug.WriteLine("WARN: " + format, args); + } + + public void Error(Exception exception) + { + Debug.WriteLine("ERROR: {0}\n{1}", _type.Name, exception); + } + } + } + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/AboutModel.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/AboutModel.cs new file mode 100644 index 00000000..2efb2225 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/AboutModel.cs @@ -0,0 +1,10 @@ +namespace Caliburn.Micro.Tutorial.Wpf.Models + { + public class AboutModel + { + public string Title { get; set; } ="Caliburn.Micro Tutorial"; + public string Version { get; set; } ="1.0"; + public string Author { get; set; } = "Rudolf"; + public string Url { get; set; } = "https://caliburnmicro.com/"; + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/CategoryModel.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/CategoryModel.cs new file mode 100644 index 00000000..3723a697 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Models/CategoryModel.cs @@ -0,0 +1,8 @@ +namespace Caliburn.Micro.Tutorial.Wpf.Models + { + public class CategoryModel + { + public string CategoryName { get; set; } + public string CategoryDescription { get; set; } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/AboutViewModel.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/AboutViewModel.cs new file mode 100644 index 00000000..a47beb21 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/AboutViewModel.cs @@ -0,0 +1,20 @@ +using Caliburn.Micro.Tutorial.Wpf.Models; +using System.Threading.Tasks; + +namespace Caliburn.Micro.Tutorial.Wpf.ViewModels + { + public class AboutViewModel: Screen + { + private AboutModel _aboutData = new AboutModel(); + + public AboutModel AboutData + { + get { return _aboutData; } + } + + public Task CloseForm() + { + return TryCloseAsync(); + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/CategoryViewModel.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/CategoryViewModel.cs new file mode 100644 index 00000000..a8dde429 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/CategoryViewModel.cs @@ -0,0 +1,124 @@ +using Caliburn.Micro.Tutorial.Wpf.Models; + +namespace Caliburn.Micro.Tutorial.Wpf.ViewModels + { + public class CategoryViewModel : Screen + { + private BindableCollection _categoryList = new BindableCollection(); + private CategoryModel _selectedCategoryModel; + private string _categoryName; + private string _categoryDescription; + + public BindableCollection CategoryList + { + get + { + return _categoryList; + } + set + { + _categoryList = value; + } + } + + public CategoryModel SelectedCategory + { + get + { + return _selectedCategoryModel; + } + + set + { + _selectedCategoryModel = value; + NotifyOfPropertyChange(nameof(SelectedCategory)); + NotifyOfPropertyChange(nameof(CanEdit)); + NotifyOfPropertyChange(nameof(CanDelete)); + } + } + + public string CategoryName + { + get => _categoryName; set + { + _categoryName = value; + NotifyOfPropertyChange(nameof(CategoryName)); + NotifyOfPropertyChange(nameof(CanSave)); + } + } + + public string CategoryDescription + { + get => _categoryDescription; set + { + _categoryDescription = value; + NotifyOfPropertyChange(nameof(CategoryDescription)); + } + } + + protected override void OnViewLoaded(object view) + { + base.OnViewLoaded(view); + CategoryList.Add(new CategoryModel { CategoryName = "Meals", CategoryDescription = "Lunches and diners" }); + CategoryList.Add(new CategoryModel { CategoryName = "Representation", CategoryDescription = "Gifts for our customers" }); + } + + + public bool CanEdit + { + get + { + return SelectedCategory != null; + } + } + + public void Edit() + { + CategoryName = SelectedCategory.CategoryName; + CategoryDescription = SelectedCategory.CategoryDescription; + } + + public bool CanDelete + { + get + { + return SelectedCategory != null; + } + } + + public void Delete() + { + CategoryList.Remove(SelectedCategory); + Clear(); + } + + public bool CanSave + { + get + { + return CategoryName?.Length > 2; + } + } + + public void Save() + { + CategoryModel newCategory = new CategoryModel(); + newCategory.CategoryName = CategoryName; + newCategory.CategoryDescription = CategoryDescription; + if (SelectedCategory != null) + { + // remove the existing category, needed to update the view + CategoryList.Remove(SelectedCategory); + } + CategoryList.Add(newCategory); + Clear(); + } + + public void Clear() + { + CategoryName = string.Empty; + CategoryDescription = string.Empty; + SelectedCategory = null; + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/ShellViewModel.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/ShellViewModel.cs new file mode 100644 index 00000000..9439d905 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/ViewModels/ShellViewModel.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Caliburn.Micro.Tutorial.Wpf.ViewModels + { + public class ShellViewModel : Conductor + { + private readonly IWindowManager _windowManager; + + public ShellViewModel(IWindowManager windowManager) + { + _windowManager= windowManager; + } + + public bool CanFileMenu + { + get + { + return false; + } + } + protected async override void OnViewLoaded(object view) + { + base.OnViewLoaded(view); + await EditCategories(); + } + + public Task EditCategories() + { + var viewmodel = IoC.Get(); + return ActivateItemAsync(viewmodel, new CancellationToken()); + } + + public Task About() + { + return _windowManager.ShowDialogAsync(IoC.Get()); + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml new file mode 100644 index 00000000..49303061 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + Program name: + + Program version: + + Author: + + More information: + + + + + + + + + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml.cs new file mode 100644 index 00000000..a3cbaabb --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/AboutView.xaml.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; +using System.Windows; + +namespace Caliburn.Micro.Tutorial.Wpf.Views + { + public partial class AboutView : Window + { + public AboutView() + { + InitializeComponent(); + } + + private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) + { + // You need a workaround here for .Net Core: + // https://github.com/dotnet/runtime/issues/28005 + var psi = new ProcessStartInfo + { + FileName = e.Uri.AbsoluteUri, + UseShellExecute = true + }; + Process.Start(psi); + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml new file mode 100644 index 00000000..75a8384c --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + Categories + + + + + + + + + + + + + Edit Category + + Category Name + + + + Category Description + + + + + + + + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml.cs new file mode 100644 index 00000000..4592012d --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/CategoryView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Caliburn.Micro.Tutorial.Wpf.Views + { + /// + /// Interaction logic for CategoryView.xaml + /// + public partial class CategoryView : UserControl + { + public CategoryView() + { + InitializeComponent(); + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml new file mode 100644 index 00000000..a325e6c4 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml.cs b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml.cs new file mode 100644 index 00000000..9625b321 --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/Caliburn.Micro.Tutorial.Wpf/Views/ShellView.xaml.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Caliburn.Micro.Tutorial.Wpf.Views + { + /// + /// Interaction logic for ShellView.xaml + /// + public partial class ShellView : Window + { + public ShellView() + { + InitializeComponent(); + } + } + } diff --git a/samples/tutorals/WPF/Wpf.Tutorial/readme.md b/samples/tutorals/WPF/Wpf.Tutorial/readme.md new file mode 100644 index 00000000..a147f42f --- /dev/null +++ b/samples/tutorals/WPF/Wpf.Tutorial/readme.md @@ -0,0 +1,6 @@ +# Wpf Tutorial + +This folder contains the solution for a WPF Tutorial for new Caliburn.Micro users. +Over time more functions will be added to the tutorial. The intention is that it will cover more advanced concepts as well. The code represents all tutorial functionality. + +[WPF Tutorial text contents page](https://www.caliburn.micro/documentation//Tutorials/wpf/Contents)