Merge branch 'dev' into Issue36-doc
This commit is contained in:
Коммит
e60ad1e7f4
|
@ -0,0 +1,25 @@
|
|||
|
||||
$rootPath = (Split-Path $PSScriptRoot)
|
||||
|
||||
$scriptPath = Join-Path $rootPath \_build\ParallelTestExecution.ps1
|
||||
$testrunnerPath = Join-Path $rootPath \Code\packages\xunit.runner.console.2.2.0\tools\xunit.console.exe
|
||||
$templateTestLibraryPath = Join-Path $rootPath \Code\test\Templates.Test\bin\Analyze\Microsoft.Templates.Test.dll
|
||||
$coreTestLibraryPath = Join-Path $rootPath \Code\test\Core.Test\bin\Analyze\Microsoft.Templates.Core.Test.dll
|
||||
$uiTestLibraryPath = Join-Path $rootPath \Code\test\UI.Test\bin\Analyze\Microsoft.UI.Test.dll
|
||||
$traits = 'ExecutionSet=BuildCodeBehind', 'ExecutionSet=BuildMVVMBasic','ExecutionSet=BuildMVVMLight','ExecutionSet=BuildCaliburnMicro', 'ExecutionSet=BuildStyleCop', 'ExecutionSet=TemplateValidation', 'ExecutionSet=BuildRightClickWithLegacy'
|
||||
$outputDir = 'C:\temp\testresults'
|
||||
|
||||
if (-not (Test-Path $outputDir))
|
||||
{
|
||||
New-Item $outputDir -type Directory
|
||||
}
|
||||
|
||||
|
||||
. $testrunnerPath $coreTestLibraryPath
|
||||
|
||||
. $testrunnerPath $uiTestLibraryPath
|
||||
|
||||
. $scriptPath $testrunnerPath $testLibraryPath $traits $outputDir
|
||||
|
||||
Write-Host $rootPath
|
||||
Write-Host $scriptPath
|
|
@ -101,7 +101,7 @@ namespace Microsoft.Templates.Core.PostActions.Catalog.Merge
|
|||
private string GetKey(XElement node)
|
||||
{
|
||||
XNamespace ns = node.GetNamespaceOfPrefix("x");
|
||||
return node.Attribute(ns + "Key").Value;
|
||||
return node.Attribute(ns + "Key")?.Value;
|
||||
}
|
||||
|
||||
private IEnumerable<XElement> GetNodesToMerge(XElement rootNode)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
@ -57,9 +56,7 @@ namespace Microsoft.Templates.UI.Controls
|
|||
|
||||
private void OnHideTimerTick(object sender, EventArgs e)
|
||||
{
|
||||
this.FadeOut();
|
||||
Panel.SetZIndex(this, 0);
|
||||
closeButton.Focusable = false;
|
||||
HideStatus();
|
||||
_hideTimer.Stop();
|
||||
}
|
||||
|
||||
|
@ -81,15 +78,24 @@ namespace Microsoft.Templates.UI.Controls
|
|||
_hideTimer.Interval = TimeSpan.FromSeconds(autoHideSeconds);
|
||||
_hideTimer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
_hideTimer.Stop();
|
||||
}
|
||||
this.FadeIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
Panel.SetZIndex(this, 0);
|
||||
closeButton.Focusable = false;
|
||||
this.FadeOut(0);
|
||||
Visibility = Visibility.Collapsed;
|
||||
HideStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void HideStatus()
|
||||
{
|
||||
this.FadeOut(0);
|
||||
Panel.SetZIndex(this, 0);
|
||||
closeButton.Focusable = false;
|
||||
Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,6 @@ namespace Microsoft.Templates.UI.Controls
|
|||
{
|
||||
public class TextBoxEx : TextBox
|
||||
{
|
||||
////public bool IsEditionEnabled
|
||||
////{
|
||||
//// get { return (bool)GetValue(IsEditionEnabledProperty); }
|
||||
//// set { SetValue(IsEditionEnabledProperty, value); }
|
||||
////}
|
||||
////public static readonly DependencyProperty IsEditionEnabledProperty = DependencyProperty.Register("IsEditionEnabled", typeof(bool), typeof(TextBoxEx), new PropertyMetadata(false));
|
||||
|
||||
public bool ForceSetFocus
|
||||
{
|
||||
get { return (bool)GetValue(IsFocusedProperty); }
|
||||
|
@ -37,12 +30,6 @@ namespace Microsoft.Templates.UI.Controls
|
|||
// FocusManager.AddLostFocusHandler(this, LostFocusHandler);
|
||||
}
|
||||
|
||||
////private void LostFocusHandler(object sender, RoutedEventArgs e)
|
||||
////{
|
||||
//// //MainViewModel.Current.ProjectTemplates.CloseTemplatesEdition();
|
||||
//// //MainViewModel.Current.ProjectTemplates.CloseSummaryItemsEdition();
|
||||
////}
|
||||
|
||||
private void UpdateFocus(bool force)
|
||||
{
|
||||
if (force)
|
||||
|
@ -57,26 +44,6 @@ namespace Microsoft.Templates.UI.Controls
|
|||
Select(0, Text.Length);
|
||||
}
|
||||
|
||||
////protected override void OnLostFocus(RoutedEventArgs e)
|
||||
////{
|
||||
//// base.OnLostFocus(e);
|
||||
//// //MainViewModel.Current.MainView.Dispatcher.Invoke(() =>
|
||||
//// //{
|
||||
//// // MainViewModel.Current.ProjectTemplates.CloseTemplatesEdition();
|
||||
//// // MainViewModel.Current.ProjectTemplates.CloseSummaryItemsEdition();
|
||||
//// //});
|
||||
////}
|
||||
|
||||
////protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
|
||||
////{
|
||||
//// base.OnLostKeyboardFocus(e);
|
||||
//// //MainViewModel.Current.MainView.Dispatcher.Invoke(() =>
|
||||
//// //{
|
||||
//// // MainViewModel.Current.ProjectTemplates.CloseTemplatesEdition();
|
||||
//// // MainViewModel.Current.ProjectTemplates.CloseSummaryItemsEdition();
|
||||
//// //});
|
||||
////}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Windows.Input;
|
|||
using Microsoft.Templates.UI.Extensions;
|
||||
using Microsoft.Templates.UI.ViewModels.NewProject;
|
||||
using Microsoft.Templates.UI.Views.NewProject;
|
||||
using Microsoft.Templates.UI.Services;
|
||||
|
||||
namespace Microsoft.Templates.UI.Controls
|
||||
{
|
||||
|
@ -70,7 +71,7 @@ namespace Microsoft.Templates.UI.Controls
|
|||
UpdateOpenStatus();
|
||||
}
|
||||
|
||||
private void OnMainGridGotFocus(object sender, RoutedEventArgs e) => MainViewModel.Current.Ordering.SetDropTarget(TogglePanelContent as SavedTemplateViewModel);
|
||||
private void OnMainGridGotFocus(object sender, RoutedEventArgs e) => OrderingService.SetDropTarget(TogglePanelContent as SavedTemplateViewModel);
|
||||
|
||||
private static void OnIsOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
|
@ -89,13 +90,13 @@ namespace Microsoft.Templates.UI.Controls
|
|||
}
|
||||
if (e.Key == Key.Space && mainGrid.IsFocused)
|
||||
{
|
||||
if (MainViewModel.Current.Ordering.SetDrag(TogglePanelContent as SavedTemplateViewModel))
|
||||
if (OrderingService.SetDrag(TogglePanelContent as SavedTemplateViewModel))
|
||||
{
|
||||
dragAndDropShadowBorder.Opacity = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MainViewModel.Current.Ordering.SetDrop(TogglePanelContent as SavedTemplateViewModel);
|
||||
OrderingService.SetDrop(TogglePanelContent as SavedTemplateViewModel);
|
||||
}
|
||||
}
|
||||
if (e.Key == Key.Escape)
|
||||
|
|
|
@ -12,14 +12,21 @@ using Microsoft.Templates.UI.ViewModels.NewProject;
|
|||
|
||||
namespace Microsoft.Templates.UI.Services
|
||||
{
|
||||
public class OrderingService
|
||||
public static class OrderingService
|
||||
{
|
||||
public StackPanel Panel { get; set; }
|
||||
public static StackPanel Panel { get; set; }
|
||||
|
||||
private SavedTemplateViewModel _dragginItem;
|
||||
private SavedTemplateViewModel _dropTarget;
|
||||
private static Func<ObservableCollection<ObservableCollection<SavedTemplateViewModel>>> _getSavedPages;
|
||||
|
||||
public void AddList(ObservableCollection<SavedTemplateViewModel> items, bool allowDragAndDrop)
|
||||
private static SavedTemplateViewModel _dragginItem;
|
||||
private static SavedTemplateViewModel _dropTarget;
|
||||
|
||||
public static void Initialize(Func<ObservableCollection<ObservableCollection<SavedTemplateViewModel>>> getSavedPages)
|
||||
{
|
||||
_getSavedPages = getSavedPages;
|
||||
}
|
||||
|
||||
public static void AddList(ObservableCollection<SavedTemplateViewModel> items, bool allowDragAndDrop)
|
||||
{
|
||||
if (Panel != null)
|
||||
{
|
||||
|
@ -40,9 +47,9 @@ namespace Microsoft.Templates.UI.Services
|
|||
}
|
||||
}
|
||||
|
||||
public void SetDropTarget(SavedTemplateViewModel savedTemplate) => _dropTarget = savedTemplate;
|
||||
public static void SetDropTarget(SavedTemplateViewModel savedTemplate) => _dropTarget = savedTemplate;
|
||||
|
||||
public bool SetDrag(SavedTemplateViewModel savedTemplate)
|
||||
public static bool SetDrag(SavedTemplateViewModel savedTemplate)
|
||||
{
|
||||
if (_dragginItem == null)
|
||||
{
|
||||
|
@ -52,13 +59,12 @@ namespace Microsoft.Templates.UI.Services
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool SetDrop(SavedTemplateViewModel savedTemplate)
|
||||
public static bool SetDrop(SavedTemplateViewModel savedTemplate)
|
||||
{
|
||||
if (_dragginItem != null && _dropTarget != null && _dragginItem.ItemName != _dropTarget.ItemName)
|
||||
{
|
||||
var savedPages = MainViewModel.Current.ProjectTemplates.SavedPages;
|
||||
var newIndex = savedPages.First().IndexOf(_dropTarget);
|
||||
var oldIndex = savedPages.First().IndexOf(_dragginItem);
|
||||
var newIndex = _getSavedPages().First().IndexOf(_dropTarget);
|
||||
var oldIndex = _getSavedPages().First().IndexOf(_dragginItem);
|
||||
Drop(null, new DragAndDropEventArgs<SavedTemplateViewModel>(null, _dropTarget, oldIndex, newIndex));
|
||||
_dragginItem = null;
|
||||
_dropTarget = null;
|
||||
|
@ -66,7 +72,7 @@ namespace Microsoft.Templates.UI.Services
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool ClearDraggin()
|
||||
public static bool ClearDraggin()
|
||||
{
|
||||
if (_dragginItem != null)
|
||||
{
|
||||
|
@ -77,12 +83,11 @@ namespace Microsoft.Templates.UI.Services
|
|||
return false;
|
||||
}
|
||||
|
||||
private void Drop(object sender, DragAndDropEventArgs<SavedTemplateViewModel> e)
|
||||
private static void Drop(object sender, DragAndDropEventArgs<SavedTemplateViewModel> e)
|
||||
{
|
||||
var savedPages = MainViewModel.Current.ProjectTemplates.SavedPages;
|
||||
if (savedPages.Count > 0 && savedPages.Count >= e.ItemData.GenGroup + 1)
|
||||
if (_getSavedPages().Count > 0 && _getSavedPages().Count >= e.ItemData.GenGroup + 1)
|
||||
{
|
||||
var items = savedPages[e.ItemData.GenGroup];
|
||||
var items = _getSavedPages()[e.ItemData.GenGroup];
|
||||
if (items.Count > 1)
|
||||
{
|
||||
if (e.NewIndex == 0)
|
||||
|
@ -91,7 +96,7 @@ namespace Microsoft.Templates.UI.Services
|
|||
}
|
||||
if (e.OldIndex > -1)
|
||||
{
|
||||
savedPages[e.ItemData.GenGroup].Move(e.OldIndex, e.NewIndex);
|
||||
_getSavedPages()[e.ItemData.GenGroup].Move(e.OldIndex, e.NewIndex);
|
||||
}
|
||||
MainViewModel.Current.ProjectTemplates.SetHomePage(items.First());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Templates.Core;
|
||||
using Microsoft.Templates.Core.Diagnostics;
|
||||
using Microsoft.Templates.UI.ViewModels.NewProject;
|
||||
using Microsoft.TemplateEngine.Abstractions;
|
||||
|
||||
namespace Microsoft.Templates.UI.Services
|
||||
{
|
||||
public static class UserSelectionService
|
||||
{
|
||||
private static Func<ObservableCollection<ObservableCollection<SavedTemplateViewModel>>> _getSavedPages;
|
||||
private static Func<ObservableCollection<SavedTemplateViewModel>> _getSavedFeatures;
|
||||
public static void Initialize(Func<ObservableCollection<ObservableCollection<SavedTemplateViewModel>>> getSavedPages, Func<ObservableCollection<SavedTemplateViewModel>> getSavedFeatures)
|
||||
{
|
||||
_getSavedPages = getSavedPages;
|
||||
_getSavedFeatures = getSavedFeatures;
|
||||
}
|
||||
|
||||
public static void SetupTemplatesFromLayout(string projectTypeName, string frameworkName)
|
||||
{
|
||||
var layout = GenComposer.GetLayoutTemplates(projectTypeName, frameworkName);
|
||||
|
||||
foreach (var item in layout)
|
||||
{
|
||||
if (item.Template != null)
|
||||
{
|
||||
AddTemplateAndDependencies((item.Layout.name, item.Template), frameworkName, !item.Layout.@readonly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddTemplateAndDependencies((string name, ITemplateInfo template) item, string frameworkName, bool isRemoveEnabled = true)
|
||||
{
|
||||
var newItem = new SavedTemplateViewModel(item, isRemoveEnabled);
|
||||
SaveNewTemplate(newItem);
|
||||
|
||||
var dependencies = GenComposer.GetAllDependencies(item.template, frameworkName);
|
||||
foreach (var dependencyTemplate in dependencies)
|
||||
{
|
||||
var dependencyItem = new SavedTemplateViewModel((dependencyTemplate.GetDefaultName(), dependencyTemplate), isRemoveEnabled);
|
||||
SaveNewTemplate(dependencyItem);
|
||||
}
|
||||
MainViewModel.Current.RebuildLicenses();
|
||||
}
|
||||
|
||||
public static bool SaveNewTemplate(SavedTemplateViewModel newItem)
|
||||
{
|
||||
if (newItem == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var identities = new List<string>();
|
||||
_getSavedPages().ToList().ForEach(spg => identities.AddRange(spg.Select(sp => sp.Identity)));
|
||||
identities.AddRange(_getSavedFeatures().Select(sf => sf.Identity));
|
||||
|
||||
if (newItem.MultipleInstance == false && identities.Any(i => i == newItem.Identity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (newItem.TemplateType == TemplateType.Page)
|
||||
{
|
||||
while (_getSavedPages().Count < newItem.GenGroup + 1)
|
||||
{
|
||||
var items = new ObservableCollection<SavedTemplateViewModel>();
|
||||
_getSavedPages().Add(items);
|
||||
OrderingService.AddList(items, _getSavedPages().Count == 1);
|
||||
}
|
||||
_getSavedPages()[newItem.GenGroup].Add(newItem);
|
||||
}
|
||||
else if (newItem.TemplateType == TemplateType.Feature)
|
||||
{
|
||||
_getSavedFeatures().Add(newItem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return null if template was removed successfully and a Existing SavedTemplate if it can not be removed becaouse this template depends on it
|
||||
public static SavedTemplateViewModel RemoveTemplate(SavedTemplateViewModel item)
|
||||
{
|
||||
// Look if is there any templates that depends on item
|
||||
SavedTemplateViewModel dependency = AnySavedTemplateDependsOnItem(item);
|
||||
if (dependency == null)
|
||||
{
|
||||
// Remove template
|
||||
if (_getSavedPages()[item.GenGroup].Contains(item))
|
||||
{
|
||||
_getSavedPages()[item.GenGroup].Remove(item);
|
||||
}
|
||||
else if (_getSavedFeatures().Contains(item))
|
||||
{
|
||||
_getSavedFeatures().Remove(item);
|
||||
}
|
||||
|
||||
TryRemoveHiddenDependencies(item);
|
||||
MainViewModel.Current.RebuildLicenses();
|
||||
AppHealth.Current.Telemetry.TrackEditSummaryItemAsync(EditItemActionEnum.Remove).FireAndForget();
|
||||
}
|
||||
return dependency;
|
||||
}
|
||||
|
||||
private static void TryRemoveHiddenDependencies(SavedTemplateViewModel item)
|
||||
{
|
||||
foreach (var identity in item.DependencyList)
|
||||
{
|
||||
var dependency = _getSavedFeatures().FirstOrDefault(sf => sf.Identity == identity);
|
||||
if (dependency == null)
|
||||
{
|
||||
foreach (var pageGroup in _getSavedPages())
|
||||
{
|
||||
dependency = pageGroup.FirstOrDefault(sf => sf.Identity == identity);
|
||||
if (dependency != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dependency != null)
|
||||
{
|
||||
// If the template is not hidden we can not remove it because it could be added in wizard
|
||||
if (dependency.IsHidden)
|
||||
{
|
||||
// Look if there are another saved template that depends on it.
|
||||
// For example, if it's added two different chart pages, when remove the first one SampleDataService can not be removed, but if no saved templates use SampleDataService, it can be removed.
|
||||
if (!_getSavedFeatures().Any(sf => sf.DependencyList.Any(d => d == dependency.Identity)) || _getSavedPages().Any(spg => spg.Any(sp => sp.DependencyList.Any(d => d == dependency.Identity))))
|
||||
{
|
||||
RemoveTemplate(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SavedTemplateViewModel AnySavedTemplateDependsOnItem(SavedTemplateViewModel item)
|
||||
{
|
||||
SavedTemplateViewModel dependencyItem = null;
|
||||
foreach (var group in _getSavedPages())
|
||||
{
|
||||
dependencyItem = group.FirstOrDefault(st => st.DependencyList.Any(d => d == item.Identity));
|
||||
if (dependencyItem != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dependencyItem == null)
|
||||
{
|
||||
dependencyItem = _getSavedFeatures().FirstOrDefault(st => st.DependencyList.Any(d => d == item.Identity));
|
||||
}
|
||||
|
||||
return dependencyItem;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -328,6 +328,7 @@
|
|||
<Compile Include="Generation\NewItemGenController.cs" />
|
||||
<Compile Include="Services\LicensesService.cs" />
|
||||
<Compile Include="Services\SystemService.cs" />
|
||||
<Compile Include="Services\UserSelectionService.cs" />
|
||||
<Compile Include="TemplateSelectors\FileExtensionTemplateSelector.cs" />
|
||||
<Compile Include="TemplateSelectors\FileStatusTemplateSelector.cs" />
|
||||
<Compile Include="TemplateSelectors\StatusBoxTemplateSelector.cs" />
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
}
|
||||
|
||||
public ObservableCollection<SummaryLicenseViewModel> Licenses { get; } = new ObservableCollection<SummaryLicenseViewModel>();
|
||||
public OrderingService Ordering { get; } = new OrderingService();
|
||||
|
||||
public MainViewModel() : base()
|
||||
{
|
||||
|
@ -55,7 +54,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
{
|
||||
WizardStatus.WizardTitle = StringRes.ProjectSetupTitle;
|
||||
NavigationService.Initialize(stepFrame, new ProjectSetupView());
|
||||
Ordering.Panel = summaryPageGroups;
|
||||
OrderingService.Panel = summaryPageGroups;
|
||||
await BaseInitializeAsync();
|
||||
}
|
||||
|
||||
|
@ -69,7 +68,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
{
|
||||
if (CheckProjectSetupChanged())
|
||||
{
|
||||
WizardStatus.SetStatus(StatusViewModel.Warning(string.Format(StringRes.ResetSelection, ProjectTemplates.ContextProjectType.DisplayName, ProjectTemplates.ContextFramework.DisplayName), true, 5));
|
||||
WizardStatus.SetStatus(StatusViewModel.Warning(string.Format(StringRes.ResetSelection, ProjectTemplates.ContextProjectType.DisplayName, ProjectTemplates.ContextFramework.DisplayName), true));
|
||||
_needRestartConfiguration = true;
|
||||
}
|
||||
else
|
||||
|
@ -139,7 +138,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
if (_needRestartConfiguration)
|
||||
{
|
||||
ResetSelection();
|
||||
Ordering.Panel.Children.Clear();
|
||||
OrderingService.Panel.Children.Clear();
|
||||
CleanStatus();
|
||||
}
|
||||
WizardStatus.WizardTitle = StringRes.ProjectPagesTitle;
|
||||
|
@ -181,7 +180,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
protected override async Task OnNewTemplatesAvailableAsync()
|
||||
{
|
||||
ResetSelection();
|
||||
Ordering.Panel.Children.Clear();
|
||||
OrderingService.Panel.Children.Clear();
|
||||
NavigationService.Navigate(new ProjectSetupView());
|
||||
await ProjectSetup.InitializeAsync(true);
|
||||
}
|
||||
|
|
|
@ -51,14 +51,14 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
public bool HasSavedPages
|
||||
{
|
||||
get => _hasSavedPages;
|
||||
private set => SetProperty(ref _hasSavedPages, value);
|
||||
set => SetProperty(ref _hasSavedPages, value);
|
||||
}
|
||||
|
||||
private bool _hasSavedFeatures;
|
||||
public bool HasSavedFeatures
|
||||
{
|
||||
get => _hasSavedFeatures;
|
||||
private set => SetProperty(ref _hasSavedFeatures, value);
|
||||
set => SetProperty(ref _hasSavedFeatures, value);
|
||||
}
|
||||
|
||||
public ProjectTemplatesViewModel()
|
||||
|
@ -66,8 +66,13 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
SavedFeatures.CollectionChanged += (s, o) => { OnPropertyChanged(nameof(SavedFeatures)); };
|
||||
SavedPages.CollectionChanged += (s, o) => { OnPropertyChanged(nameof(SavedPages)); };
|
||||
ValidationService.Initialize(GetNames);
|
||||
UserSelectionService.Initialize(GetSavedPages, GetSavedFeatures);
|
||||
OrderingService.Initialize(GetSavedPages);
|
||||
}
|
||||
|
||||
private ObservableCollection<SavedTemplateViewModel> GetSavedFeatures() => SavedFeatures;
|
||||
private ObservableCollection<ObservableCollection<SavedTemplateViewModel>> GetSavedPages() => SavedPages;
|
||||
|
||||
private IEnumerable<string> GetNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
|
@ -76,17 +81,6 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
return names;
|
||||
}
|
||||
|
||||
public IEnumerable<string> Identities
|
||||
{
|
||||
get
|
||||
{
|
||||
var identities = new List<string>();
|
||||
SavedPages.ToList().ForEach(spg => identities.AddRange(spg.Select(sp => sp.Identity)));
|
||||
identities.AddRange(SavedFeatures.Select(sf => sf.Identity));
|
||||
return identities;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
ContextProjectType = MainViewModel.Current.ProjectSetup.SelectedProjectType;
|
||||
|
@ -106,8 +100,16 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
|
||||
if (SavedPages.Count == 0 && SavedFeatures.Count == 0)
|
||||
{
|
||||
SetupTemplatesFromLayout(ContextProjectType.Name, ContextFramework.Name);
|
||||
MainViewModel.Current.RebuildLicenses();
|
||||
UserSelectionService.SetupTemplatesFromLayout(ContextProjectType.Name, ContextFramework.Name);
|
||||
UpdateTemplatesAvailability();
|
||||
UpdateSummaryTemplates();
|
||||
UpdateHasPagesAndHasFeatures();
|
||||
if (HasSavedPages)
|
||||
{
|
||||
var firstPage = SavedPages.First().First();
|
||||
HomeName = firstPage.ItemName;
|
||||
firstPage.IsHome = true;
|
||||
}
|
||||
}
|
||||
CloseAllEditions();
|
||||
await Task.CompletedTask;
|
||||
|
@ -127,103 +129,18 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
AppHealth.Current.Telemetry.TrackEditSummaryItemAsync(EditItemActionEnum.SetHome).FireAndForget();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateHomePageName(string name) => HomeName = name;
|
||||
|
||||
public void RemoveTemplate(SavedTemplateViewModel item, bool showErrors)
|
||||
public bool IsTemplateAlreadyDefined(string identity)
|
||||
{
|
||||
// Look if is there any templates that depends on item
|
||||
if (AnySavedTemplateDependsOnItem(item, showErrors))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove template
|
||||
if (SavedPages[item.GenGroup].Contains(item))
|
||||
{
|
||||
SavedPages[item.GenGroup].Remove(item);
|
||||
HasSavedPages = SavedPages.Any(g => g.Any());
|
||||
}
|
||||
else if (SavedFeatures.Contains(item))
|
||||
{
|
||||
SavedFeatures.Remove(item);
|
||||
HasSavedFeatures = SavedFeatures.Any();
|
||||
}
|
||||
|
||||
TryRemoveHiddenDependencies(item);
|
||||
|
||||
MainViewModel.Current.FinishCommand.OnCanExecuteChanged();
|
||||
UpdateTemplatesAvailability();
|
||||
MainViewModel.Current.RebuildLicenses();
|
||||
|
||||
AppHealth.Current.Telemetry.TrackEditSummaryItemAsync(EditItemActionEnum.Remove).FireAndForget();
|
||||
var identities = new List<string>();
|
||||
SavedPages.ToList().ForEach(spg => identities.AddRange(spg.Select(sp => sp.Identity)));
|
||||
identities.AddRange(SavedFeatures.Select(sf => sf.Identity));
|
||||
return identities.Any(i => i == identity);
|
||||
}
|
||||
|
||||
private bool AnySavedTemplateDependsOnItem(SavedTemplateViewModel item, bool showErrors)
|
||||
{
|
||||
SavedTemplateViewModel dependencyItem = null;
|
||||
foreach (var group in SavedPages)
|
||||
{
|
||||
dependencyItem = group.FirstOrDefault(st => st.DependencyList.Any(d => d == item.Identity));
|
||||
if (dependencyItem != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dependencyItem == null)
|
||||
{
|
||||
dependencyItem = SavedFeatures.FirstOrDefault(st => st.DependencyList.Any(d => d == item.Identity));
|
||||
}
|
||||
|
||||
if (dependencyItem != null)
|
||||
{
|
||||
if (showErrors)
|
||||
{
|
||||
string message = string.Format(StringRes.ValidationError_CanNotRemoveTemplate_SF, item.TemplateName, dependencyItem.TemplateName, dependencyItem.TemplateType);
|
||||
MainViewModel.Current.WizardStatus.SetStatus(StatusViewModel.Warning(message, false, 5));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void TryRemoveHiddenDependencies(SavedTemplateViewModel item)
|
||||
{
|
||||
foreach (var identity in item.DependencyList)
|
||||
{
|
||||
var dependency = SavedFeatures.FirstOrDefault(sf => sf.Identity == identity);
|
||||
if (dependency == null)
|
||||
{
|
||||
foreach (var pageGroup in SavedPages)
|
||||
{
|
||||
dependency = pageGroup.FirstOrDefault(sf => sf.Identity == identity);
|
||||
if (dependency != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dependency != null)
|
||||
{
|
||||
// If the template is not hidden we can not remove it because it could be added in wizard
|
||||
if (dependency.IsHidden)
|
||||
{
|
||||
// Look if there are another saved template that depends on it.
|
||||
// For example, if it's added two different chart pages, when remove the first one SampleDataService can not be removed, but if no saved templates use SampleDataService, it can be removed.
|
||||
if (!SavedFeatures.Any(sf => sf.DependencyList.Any(d => d == dependency.Identity)) || SavedPages.Any(spg => spg.Any(sp => sp.DependencyList.Any(d => d == dependency.Identity))))
|
||||
{
|
||||
RemoveTemplate(dependency, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTemplateAlreadyDefined(string identity) => Identities.Any(i => i == identity);
|
||||
|
||||
private void UpdateTemplatesAvailability()
|
||||
public void UpdateTemplatesAvailability()
|
||||
{
|
||||
PagesGroups.ToList().ForEach(g => g.Templates.ToList().ForEach(t =>
|
||||
{
|
||||
|
@ -238,7 +155,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
}));
|
||||
}
|
||||
|
||||
private void UpdateSummaryTemplates()
|
||||
public void UpdateSummaryTemplates()
|
||||
{
|
||||
foreach (var spg in SavedPages)
|
||||
{
|
||||
|
@ -246,64 +163,6 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
}
|
||||
}
|
||||
|
||||
private void SetupTemplatesFromLayout(string projectTypeName, string frameworkName)
|
||||
{
|
||||
var layout = GenComposer.GetLayoutTemplates(projectTypeName, frameworkName);
|
||||
|
||||
foreach (var item in layout)
|
||||
{
|
||||
if (item.Template != null)
|
||||
{
|
||||
AddTemplateAndDependencies((item.Layout.name, item.Template), !item.Layout.@readonly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTemplateAndDependencies((string name, ITemplateInfo template) item, bool isRemoveEnabled = true)
|
||||
{
|
||||
SaveNewTemplate(item, isRemoveEnabled);
|
||||
|
||||
foreach (var dependencyTemplate in GenComposer.GetAllDependencies(item.template, ContextFramework.Name))
|
||||
{
|
||||
SaveNewTemplate((dependencyTemplate.GetDefaultName(), dependencyTemplate), isRemoveEnabled);
|
||||
}
|
||||
|
||||
MainViewModel.Current.RebuildLicenses();
|
||||
}
|
||||
|
||||
private void SaveNewTemplate((string name, ITemplateInfo template) item, bool isRemoveEnabled = true)
|
||||
{
|
||||
if (item.template.GetMultipleInstance() == false && IsTemplateAlreadyDefined(item.template.Identity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var newItem = new SavedTemplateViewModel(item, isRemoveEnabled);
|
||||
|
||||
if (item.template.GetTemplateType() == TemplateType.Page)
|
||||
{
|
||||
if (SavedPages.Count == 0)
|
||||
{
|
||||
HomeName = item.name;
|
||||
newItem.IsHome = true;
|
||||
}
|
||||
while (SavedPages.Count < newItem.GenGroup + 1)
|
||||
{
|
||||
var items = new ObservableCollection<SavedTemplateViewModel>();
|
||||
SavedPages.Add(items);
|
||||
MainViewModel.Current.Ordering.AddList(items, SavedPages.Count == 1);
|
||||
}
|
||||
SavedPages[newItem.GenGroup].Add(newItem);
|
||||
HasSavedPages = true;
|
||||
}
|
||||
else if (item.template.GetTemplateType() == TemplateType.Feature)
|
||||
{
|
||||
SavedFeatures.Add(newItem);
|
||||
HasSavedFeatures = true;
|
||||
}
|
||||
UpdateTemplatesAvailability();
|
||||
UpdateSummaryTemplates();
|
||||
}
|
||||
|
||||
// UI Changes
|
||||
public bool CloseAllEditions()
|
||||
{
|
||||
|
@ -345,5 +204,11 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
target.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateHasPagesAndHasFeatures()
|
||||
{
|
||||
HasSavedPages = SavedPages.Any(g => g.Any());
|
||||
HasSavedFeatures = SavedFeatures.Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ using Microsoft.TemplateEngine.Abstractions;
|
|||
using Microsoft.Templates.UI.Services;
|
||||
using Microsoft.Templates.UI.Extensions;
|
||||
using Microsoft.Templates.Core.Diagnostics;
|
||||
using Microsoft.Templates.UI.Resources;
|
||||
using Microsoft.Templates.UI.ViewModels.Common;
|
||||
|
||||
namespace Microsoft.Templates.UI.ViewModels.NewProject
|
||||
{
|
||||
|
@ -87,6 +89,13 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
set => SetProperty(ref _isHidden, value);
|
||||
}
|
||||
|
||||
private bool _multipleInstance;
|
||||
public bool MultipleInstance
|
||||
{
|
||||
get => _multipleInstance;
|
||||
set => SetProperty(ref _multipleInstance, value);
|
||||
}
|
||||
|
||||
private string _templateName;
|
||||
public string TemplateName
|
||||
{
|
||||
|
@ -260,8 +269,10 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
Identity = item.template.Identity;
|
||||
TemplateName = item.template.Name;
|
||||
IsHidden = item.template.GetIsHidden();
|
||||
MultipleInstance = item.template.GetMultipleInstance();
|
||||
DependencyList = item.template.GetDependencyList();
|
||||
IsRemoveEnabled = isRemoveEnabled;
|
||||
|
||||
ItemForeground = GetItemForeground(true);
|
||||
AuthorForeground = GetAuthorForeground(true);
|
||||
AllowDragAndDrop = false;
|
||||
|
@ -279,7 +290,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
IsOpen = false;
|
||||
IsOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,7 +376,21 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
Close();
|
||||
}
|
||||
|
||||
private void OnRemove() => MainViewModel.Current.ProjectTemplates.RemoveTemplate(this, true);
|
||||
private void OnRemove()
|
||||
{
|
||||
var dependency = UserSelectionService.RemoveTemplate(this);
|
||||
if (dependency != null)
|
||||
{
|
||||
string message = string.Format(StringRes.ValidationError_CanNotRemoveTemplate_SF, this.TemplateName, dependency.TemplateName, dependency.TemplateType);
|
||||
MainViewModel.Current.WizardStatus.SetStatus(StatusViewModel.Warning(message, false, 5));
|
||||
}
|
||||
else
|
||||
{
|
||||
MainViewModel.Current.FinishCommand.OnCanExecuteChanged();
|
||||
MainViewModel.Current.ProjectTemplates.UpdateTemplatesAvailability();
|
||||
MainViewModel.Current.ProjectTemplates.UpdateHasPagesAndHasFeatures();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConfirmRename()
|
||||
{
|
||||
|
|
|
@ -269,7 +269,7 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
}
|
||||
else
|
||||
{
|
||||
MainViewModel.Current.ProjectTemplates.AddTemplateAndDependencies((NewTemplateName, Template), false);
|
||||
SaveItem();
|
||||
UpdateTemplateAvailability(MainViewModel.Current.ProjectTemplates.IsTemplateAlreadyDefined(Template.Identity));
|
||||
}
|
||||
}
|
||||
|
@ -278,10 +278,18 @@ namespace Microsoft.Templates.UI.ViewModels.NewProject
|
|||
{
|
||||
if (IsValidName)
|
||||
{
|
||||
MainViewModel.Current.ProjectTemplates.AddTemplateAndDependencies((NewTemplateName, Template), false);
|
||||
SaveItem();
|
||||
CloseEdition();
|
||||
UpdateTemplateAvailability(MainViewModel.Current.ProjectTemplates.IsTemplateAlreadyDefined(Template.Identity));
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveItem()
|
||||
{
|
||||
UserSelectionService.AddTemplateAndDependencies((NewTemplateName, Template), MainViewModel.Current.ProjectTemplates.ContextFramework.Name, false);
|
||||
MainViewModel.Current.ProjectTemplates.UpdateTemplatesAvailability();
|
||||
MainViewModel.Current.ProjectTemplates.UpdateSummaryTemplates();
|
||||
MainViewModel.Current.ProjectTemplates.UpdateHasPagesAndHasFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ using System.Windows.Input;
|
|||
|
||||
using Microsoft.Templates.UI.Controls;
|
||||
using Microsoft.Templates.UI.ViewModels.NewProject;
|
||||
using Microsoft.Templates.UI.Services;
|
||||
|
||||
namespace Microsoft.Templates.UI.Views.NewProject
|
||||
{
|
||||
|
@ -54,7 +55,7 @@ namespace Microsoft.Templates.UI.Views.NewProject
|
|||
{
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
if (!ViewModel.ProjectTemplates.CloseAllEditions() && !ViewModel.Ordering.ClearDraggin())
|
||||
if (!ViewModel.ProjectTemplates.CloseAllEditions() && !OrderingService.ClearDraggin())
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Microsoft.Templates.Core.Test
|
|||
{
|
||||
[Collection("Unit Test Templates")]
|
||||
[Trait("ExecutionSet", "Minimum")]
|
||||
|
||||
public class NamingTests
|
||||
{
|
||||
private TemplatesFixture _fixture;
|
||||
|
|
|
@ -110,32 +110,13 @@ namespace Microsoft.Templates.Test
|
|||
int emptyProjecFileCount = Directory.GetFiles(project, "*.*", SearchOption.AllDirectories).Count();
|
||||
Assert.True(emptyProjecFileCount > 2);
|
||||
|
||||
// Add new items
|
||||
var rightClickTemplates = _fixture.Templates().Where(
|
||||
t => (t.GetTemplateType() == TemplateType.Feature || t.GetTemplateType() == TemplateType.Page)
|
||||
&& t.GetFrameworkList().Contains(framework)
|
||||
&& !t.GetIsHidden()
|
||||
&& t.GetRightClickEnabled());
|
||||
t => (t.GetTemplateType() == TemplateType.Feature || t.GetTemplateType() == TemplateType.Page)
|
||||
&& t.GetFrameworkList().Contains(framework)
|
||||
&& !t.GetIsHidden()
|
||||
&& t.GetRightClickEnabled());
|
||||
|
||||
foreach (var item in rightClickTemplates)
|
||||
{
|
||||
OutputPath = GenContext.GetTempGenerationPath(projectName);
|
||||
|
||||
var newUserSelection = new UserSelection
|
||||
{
|
||||
ProjectType = projectType,
|
||||
Framework = framework,
|
||||
HomeName = "",
|
||||
Language = language,
|
||||
ItemGenerationType = ItemGenerationType.GenerateAndMerge
|
||||
};
|
||||
|
||||
_fixture.AddItem(newUserSelection, item, GenerationFixture.GetDefaultName);
|
||||
|
||||
await NewItemGenController.Instance.UnsafeGenerateNewItemAsync(item.GetTemplateType(), newUserSelection);
|
||||
|
||||
NewItemGenController.Instance.UnsafeFinishGeneration(newUserSelection);
|
||||
}
|
||||
await AddRightClickTemplatesAsync(rightClickTemplates, projectName, projectType, framework, language);
|
||||
|
||||
var finalProjectPath = Path.Combine(_fixture.TestNewItemPath, projectName);
|
||||
int finalProjectFileCount = Directory.GetFiles(finalProjectPath, "*.*", SearchOption.AllDirectories).Count();
|
||||
|
@ -156,6 +137,31 @@ namespace Microsoft.Templates.Test
|
|||
|
||||
return finalProjectPath;
|
||||
}
|
||||
|
||||
protected async Task AddRightClickTemplatesAsync(IEnumerable<ITemplateInfo> rightClickTemplates, string projectName, string projectType, string framework, string language)
|
||||
{
|
||||
// Add new items
|
||||
foreach (var item in rightClickTemplates)
|
||||
{
|
||||
OutputPath = GenContext.GetTempGenerationPath(projectName);
|
||||
|
||||
var newUserSelection = new UserSelection
|
||||
{
|
||||
ProjectType = projectType,
|
||||
Framework = framework,
|
||||
HomeName = "",
|
||||
Language = language,
|
||||
ItemGenerationType = ItemGenerationType.GenerateAndMerge
|
||||
};
|
||||
|
||||
_fixture.AddItem(newUserSelection, item, GenerationFixture.GetDefaultName);
|
||||
|
||||
await NewItemGenController.Instance.UnsafeGenerateNewItemAsync(item.GetTemplateType(), newUserSelection);
|
||||
|
||||
NewItemGenController.Instance.UnsafeFinishGeneration(newUserSelection);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<(string ProjectPath, string ProjecName)> AssertGenerationOneByOneAsync(string itemName, string projectType, string framework, string itemId, string language, bool cleanGeneration = true)
|
||||
{
|
||||
await SetUpFixtureForTestingAsync(language);
|
||||
|
@ -245,6 +251,9 @@ namespace Microsoft.Templates.Test
|
|||
result = context.Factory.Run(() => BuildCaliburnMicroFixture.GetProjectTemplatesAsync(framework));
|
||||
break;
|
||||
|
||||
case "LegacyFrameworks":
|
||||
result = context.Factory.Run(() => BuildRightClickWithLegacyFixture.GetProjectTemplatesAsync());
|
||||
break;
|
||||
default:
|
||||
result = context.Factory.Run(() => BuildFixture.GetProjectTemplatesAsync());
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Microsoft.Templates.Test
|
|||
{
|
||||
[Collection("BuildCaliburnMicroCollection")]
|
||||
[Trait("ExecutionSet", "BuildCaliburnMicro")]
|
||||
[Trait("ExecutionSet", "Build")]
|
||||
public class BuildCaliburnMicroProjectTests : BaseGenAndBuildTests
|
||||
{
|
||||
public BuildCaliburnMicroProjectTests(BuildCaliburnMicroFixture fixture)
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Microsoft.Templates.Test
|
|||
{
|
||||
[Collection("BuildCodeBehindCollection")]
|
||||
[Trait("ExecutionSet", "BuildCodeBehind")]
|
||||
[Trait("ExecutionSet", "Build")]
|
||||
public class BuildCodeBehindProjectTests : BaseGenAndBuildTests
|
||||
{
|
||||
public BuildCodeBehindProjectTests(BuildCodeBehindFixture fixture)
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Microsoft.Templates.Test
|
|||
{
|
||||
[Collection("BuildMVVMBasicCollection")]
|
||||
[Trait("ExecutionSet", "BuildMVVMBasic")]
|
||||
[Trait("ExecutionSet", "Build")]
|
||||
public class BuildMVVMBasicProjectTests : BaseGenAndBuildTests
|
||||
{
|
||||
public BuildMVVMBasicProjectTests(BuildMVVMBasicFixture fixture)
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Microsoft.Templates.Test
|
|||
{
|
||||
[Collection("BuildMVVMLightCollection")]
|
||||
[Trait("ExecutionSet", "BuildMVVMLight")]
|
||||
[Trait("ExecutionSet", "Build")]
|
||||
public class BuildMVVMLightProjectTests : BaseGenAndBuildTests
|
||||
{
|
||||
public BuildMVVMLightProjectTests(BuildMVVMLightFixture fixture)
|
||||
|
@ -73,7 +72,6 @@ namespace Microsoft.Templates.Test
|
|||
[Trait("Type", "BuildRandomNames")]
|
||||
[Trait("ExecutionSet", "Minimum")]
|
||||
[Trait("ExecutionSet", "BuildMinimum")]
|
||||
|
||||
public async Task BuildAllPagesAndFeaturesRandomNamesAsync(string projectType, string framework, string language)
|
||||
{
|
||||
Func<ITemplateInfo, bool> selector =
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Templates.Test
|
||||
{
|
||||
[CollectionDefinition("BuildRightClickWithLegacyCollection")]
|
||||
public class BuildRightClickWithLegacyCollection : ICollectionFixture<BuildRightClickWithLegacyFixture>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.TemplateEngine.Abstractions;
|
||||
using Microsoft.Templates.Core;
|
||||
using Microsoft.Templates.Core.Gen;
|
||||
using Microsoft.Templates.Core.Locations;
|
||||
using Microsoft.Templates.Fakes;
|
||||
using Microsoft.Templates.UI;
|
||||
|
||||
namespace Microsoft.Templates.Test
|
||||
{
|
||||
public sealed class BuildRightClickWithLegacyFixture : BaseGenAndBuildFixture, IDisposable
|
||||
{
|
||||
private string testExecutionTimeStamp = DateTime.Now.FormatAsDateHoursMinutes();
|
||||
public override string GetTestRunPath() => $"{Path.GetPathRoot(Environment.CurrentDirectory)}\\UIT\\LEG\\{testExecutionTimeStamp}\\";
|
||||
|
||||
public TemplatesSource Source => new LegacyTemplatesSource();
|
||||
public TemplatesSource LocalSource => new LocalTemplatesSource("BuildRightClickWithLegacy");
|
||||
|
||||
private static bool syncExecuted;
|
||||
|
||||
public static async Task<IEnumerable<object[]>> GetProjectTemplatesAsync()
|
||||
{
|
||||
List<object[]> result = new List<object[]>();
|
||||
foreach (var language in ProgrammingLanguages.GetAllLanguages())
|
||||
{
|
||||
await InitializeTemplatesForLanguageAsync(new LegacyTemplatesSource(), language);
|
||||
|
||||
var projectTemplates = GenContext.ToolBox.Repo.GetAll().Where(t => t.GetTemplateType() == TemplateType.Project
|
||||
&& t.GetLanguage() == language);
|
||||
|
||||
foreach (var projectTemplate in projectTemplates)
|
||||
{
|
||||
var projectTypeList = projectTemplate.GetProjectTypeList();
|
||||
|
||||
foreach (var projectType in projectTypeList)
|
||||
{
|
||||
var frameworks = GenComposer.GetSupportedFx(projectType);
|
||||
|
||||
foreach (var framework in frameworks)
|
||||
{
|
||||
result.Add(new object[] { projectType, framework, language });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static async Task InitializeTemplatesForLanguageAsync(TemplatesSource source, string language)
|
||||
{
|
||||
GenContext.Bootstrap(source, new FakeGenShell(language), language);
|
||||
|
||||
if (!syncExecuted)
|
||||
{
|
||||
await GenContext.ToolBox.Repo.SynchronizeAsync();
|
||||
syncExecuted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
await GenContext.ToolBox.Repo.RefreshAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ChangeTemplatesSourceAsync(TemplatesSource source, string language)
|
||||
{
|
||||
GenContext.Bootstrap(source, new FakeGenShell(language), language);
|
||||
await GenContext.ToolBox.Repo.SynchronizeAsync();
|
||||
}
|
||||
|
||||
public override async Task InitializeFixtureAsync(string language, IContextProvider contextProvider)
|
||||
{
|
||||
GenContext.Current = contextProvider;
|
||||
|
||||
await InitializeTemplatesForLanguageAsync(Source, language);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Templates.Core;
|
||||
using Microsoft.Templates.Core.Gen;
|
||||
using Microsoft.Templates.Core.Locations;
|
||||
using Microsoft.Templates.Fakes;
|
||||
using Microsoft.Templates.UI;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Microsoft.TemplateEngine.Abstractions;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Templates.Test
|
||||
{
|
||||
[Collection("BuildRightClickWithLegacyCollection")]
|
||||
public class BuildRightClickWithLegacyTests : BaseGenAndBuildTests
|
||||
{
|
||||
// Excluded wts.Page.WebView from this test as webview requires creator update as min target version
|
||||
private string[] excludedTemplates = { "wts.Page.WebView" };
|
||||
|
||||
public BuildRightClickWithLegacyTests(BuildRightClickWithLegacyFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetProjectTemplatesForBuildAsync", "LegacyFrameworks")]
|
||||
[Trait("ExecutionSet", "BuildRightClickWithLegacy")]
|
||||
[Trait("Type", "BuildRightClickLegacy")]
|
||||
public async Task BuildEmptyProjectWithAllRightClickItemsAsync(string projectType, string framework, string language)
|
||||
{
|
||||
var projectName = $"{projectType}{framework}Legacy";
|
||||
|
||||
Func<ITemplateInfo, bool> selector =
|
||||
t => t.GetTemplateType() == TemplateType.Project
|
||||
&& t.GetProjectTypeList().Contains(projectType)
|
||||
&& t.GetFrameworkList().Contains(framework)
|
||||
&& !t.GetIsHidden()
|
||||
&& t.GetLanguage() == language;
|
||||
|
||||
var projectPath = await AssertGenerateProjectAsync(selector, projectName, projectType, framework, language, null, false);
|
||||
|
||||
var fixture = (_fixture as BuildRightClickWithLegacyFixture);
|
||||
await fixture.ChangeTemplatesSourceAsync(fixture.LocalSource, language);
|
||||
|
||||
var rightClickTemplates = _fixture.Templates().Where(
|
||||
t => (t.GetTemplateType() == TemplateType.Feature || t.GetTemplateType() == TemplateType.Page)
|
||||
&& t.GetFrameworkList().Contains(framework)
|
||||
&& !excludedTemplates.Contains(t.GroupIdentity)
|
||||
&& !t.GetIsHidden()
|
||||
&& t.GetRightClickEnabled());
|
||||
|
||||
await AddRightClickTemplatesAsync(rightClickTemplates, projectName, projectType, framework, language);
|
||||
|
||||
AssertBuildProjectAsync(projectPath, projectName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetProjectTemplatesForBuildAsync", "LegacyFrameworks")]
|
||||
[Trait("ExecutionSet", "ManualOnly")]
|
||||
public async Task GenerateLegacyProjectWithAllPagesAndFeaturesAsync(string projectType, string framework, string language)
|
||||
{
|
||||
var projectName = $"{projectType}{framework}AllLegacy";
|
||||
|
||||
Func<ITemplateInfo, bool> selector =
|
||||
t => t.GetTemplateType() == TemplateType.Project
|
||||
&& t.GetProjectTypeList().Contains(projectType)
|
||||
&& t.GetFrameworkList().Contains(framework)
|
||||
&& !t.GetIsHidden()
|
||||
&& t.GetLanguage() == language;
|
||||
|
||||
var projectPath = await AssertGenerateProjectAsync(selector, projectName, projectType, framework, language, BaseGenAndBuildFixture.GetDefaultName, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Microsoft.Templates.Core;
|
||||
using Microsoft.Templates.Core.Diagnostics;
|
||||
using Microsoft.Templates.Core.Locations;
|
||||
using Microsoft.Templates.Core.Resources;
|
||||
|
||||
namespace Microsoft.Templates.Test
|
||||
{
|
||||
public sealed class LegacyTemplatesSource : TemplatesSource
|
||||
{
|
||||
private static string TemplatesVersion { get; } = "1.3.17255.01";
|
||||
private string TemplatesPackageFileName { get; } = $"pro.version_{TemplatesVersion}.mstx";
|
||||
|
||||
private readonly string _cdnUrl = "https://wtsrepository.blob.core.windows.net/pro/";
|
||||
|
||||
public override bool ForcedAcquisition => true;
|
||||
|
||||
public override string Id => "TestBuildLegacy";
|
||||
|
||||
protected override string AcquireMstx()
|
||||
{
|
||||
var tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
var sourceUrl = $"{_cdnUrl}/{TemplatesPackageFileName}";
|
||||
var fileTarget = Path.Combine(tempFolder, TemplatesPackageFileName);
|
||||
|
||||
Fs.EnsureFolder(tempFolder);
|
||||
|
||||
DownloadContent(sourceUrl, fileTarget);
|
||||
|
||||
return fileTarget;
|
||||
}
|
||||
|
||||
private static void DownloadContent(string sourceUrl, string file)
|
||||
{
|
||||
var wc = new WebClient();
|
||||
|
||||
wc.DownloadFile(sourceUrl, file);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -133,6 +133,10 @@
|
|||
<Compile Include="BuildCodeBehindTests\BuildCodeBehindProjectsTests.cs" />
|
||||
<Compile Include="BuildCodeBehindTests\BuildCodeBehindFixture.cs" />
|
||||
<Compile Include="BuildFixture.cs" />
|
||||
<Compile Include="BuildRightClickWithLegacy\BuildRightClickWithLegacyCollection.cs" />
|
||||
<Compile Include="BuildRightClickWithLegacy\BuildRightClickWithLegacyFixture.cs" />
|
||||
<Compile Include="BuildRightClickWithLegacy\BuildRightClickWithLegacyTests.cs" />
|
||||
<Compile Include="BuildRightClickWithLegacy\LegacyTemplatesSource.cs" />
|
||||
<Compile Include="GenTests\GenerationCollection.cs" />
|
||||
<Compile Include="GenTests\GenProjectsTests.cs" />
|
||||
<Compile Include="FileEncodingTests.cs" />
|
||||
|
|
|
@ -15,7 +15,7 @@ using Xunit;
|
|||
namespace Microsoft.Templates.Test
|
||||
{
|
||||
[Collection("BuildCollection")]
|
||||
[Trait("ExecutionSet", "ManualOnly")]
|
||||
[Trait("ExecutionSet", "LongRunning")]
|
||||
public class WindowsAppCertKitTests : BaseGenAndBuildTests
|
||||
{
|
||||
public WindowsAppCertKitTests(BuildFixture fixture)
|
||||
|
|
|
@ -10,6 +10,7 @@ using Microsoft.Templates.UI.ViewModels.NewProject;
|
|||
using Microsoft.Templates.UI.ViewModels.Common;
|
||||
|
||||
using Xunit;
|
||||
using Microsoft.Templates.UI.Services;
|
||||
|
||||
namespace Microsoft.UI.Test
|
||||
{
|
||||
|
@ -57,38 +58,93 @@ namespace Microsoft.UI.Test
|
|||
public async Task ResolveDependenciesAsync()
|
||||
{
|
||||
// Default configuration: SplitView, CodeBehind, Blank page
|
||||
var testFrameworkName = "MVVMBasic";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == "MVVMBasic");
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == testFrameworkName);
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
var settingsPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings");
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("Settings", settingsPage.Template));
|
||||
UserSelectionService.AddTemplateAndDependencies(("Settings", settingsPage.Template), testFrameworkName);
|
||||
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.Count == 2);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.ElementAt(0).Count == 1);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.ElementAt(1).Count == 1);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.Count == 2, "Non expected result: two page groups");
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.ElementAt(0).Count == 1, "Non expected result: One blank page");
|
||||
Assert.True(viewModel.ProjectTemplates.SavedPages.ElementAt(1).Count == 1, "Non expected result: One settings page");
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1, "Non expected result: One SettingStorage feature");
|
||||
}
|
||||
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1); // SettingsStorage feature added bt SettingsPage
|
||||
Assert.True(viewModel.Licenses.Count == 2); // Newtonsoft.Json added by SettingsStorage and Microsoft.Toolkit.Uwp added by MVVM Basic
|
||||
public async Task ResolveDependenciesAndLicensesAsync()
|
||||
{
|
||||
// Default configuration: SplitView, CodeBehind, Blank page
|
||||
var testFrameworkName = "MVVMBasic";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == testFrameworkName);
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
var settingsPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings");
|
||||
UserSelectionService.AddTemplateAndDependencies(("Settings", settingsPage.Template), testFrameworkName);
|
||||
Assert.True(viewModel.Licenses.Count == 2, "Non expected result: two licenses Microsoft.Toolkit.Uwp and Newtonsoft.Json");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanNotRemoveTemplateWithDependencyAsync()
|
||||
{
|
||||
// Default configuration: SplitView, CodeBehind, Blank page
|
||||
var testFrameworkName = "MVVMBasic";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == testFrameworkName);
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
var settingsPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings");
|
||||
UserSelectionService.AddTemplateAndDependencies(("Settings", settingsPage.Template), testFrameworkName);
|
||||
UserSelectionService.RemoveTemplate(viewModel.ProjectTemplates.SavedFeatures.First());
|
||||
|
||||
// SettingsStorage can not be removed because Settings page depends on it
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1, "Settings page has been removed");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveHiddenFeaturesAsync()
|
||||
{
|
||||
// Default configuration: SplitView, CodeBehind, Blank page
|
||||
var testFrameworkName = "MVVMBasic";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == testFrameworkName);
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
|
||||
var gridPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Grid");
|
||||
UserSelectionService.AddTemplateAndDependencies(("Grid", gridPage.Template), testFrameworkName);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1, "Non expected result: Sample data filter");
|
||||
|
||||
var chartPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Chart");
|
||||
UserSelectionService.AddTemplateAndDependencies(("Chart", chartPage.Template), testFrameworkName);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1, "Non expected result: Sample data filter");
|
||||
|
||||
UserSelectionService.RemoveTemplate(viewModel.ProjectTemplates.SavedPages.First()[1]);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 1, "Non expected result: Sample data filter");
|
||||
|
||||
UserSelectionService.RemoveTemplate(viewModel.ProjectTemplates.SavedPages.First()[1]);
|
||||
Assert.True(viewModel.ProjectTemplates.SavedFeatures.Count == 0, "No features expected");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateHomePageAsync()
|
||||
{
|
||||
// Configuration: SplitView, MVVM Basic, Blank page
|
||||
var testFrameworkName = "MVVMBasic";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == "MVVMBasic");
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
var settingsPage = FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings");
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("Page1", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template));
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("Page2", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template));
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("Page3", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template));
|
||||
UserSelectionService.AddTemplateAndDependencies(("Page1", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template), testFrameworkName);
|
||||
UserSelectionService.AddTemplateAndDependencies(("Page2", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template), testFrameworkName);
|
||||
UserSelectionService.AddTemplateAndDependencies(("Page3", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Blank").Template), testFrameworkName);
|
||||
|
||||
// Drag Page1 in position 1 to Main in position 0
|
||||
viewModel.Ordering.SetDrag(viewModel.ProjectTemplates.SavedPages.First().ElementAt(1));
|
||||
viewModel.Ordering.SetDropTarget(viewModel.ProjectTemplates.SavedPages.First().ElementAt(0));
|
||||
viewModel.Ordering.SetDrop(viewModel.ProjectTemplates.SavedPages.First().ElementAt(0));
|
||||
OrderingService.SetDrag(viewModel.ProjectTemplates.SavedPages.First().ElementAt(1));
|
||||
OrderingService.SetDropTarget(viewModel.ProjectTemplates.SavedPages.First().ElementAt(0));
|
||||
OrderingService.SetDrop(viewModel.ProjectTemplates.SavedPages.First().ElementAt(0));
|
||||
|
||||
// Check that Page1 is in position 0 and is the current Home Page
|
||||
Assert.True(viewModel.ProjectTemplates.HomeName == "Page1");
|
||||
|
@ -99,17 +155,18 @@ namespace Microsoft.UI.Test
|
|||
public async Task RebuildLicensesAsync()
|
||||
{
|
||||
// Default configuration: SplitView, Code Behind, Blank page - 0 Licenses
|
||||
var testFrameworkName = "MVVMLight";
|
||||
var viewModel = new MainViewModel();
|
||||
await viewModel.ProjectSetup.InitializeAsync();
|
||||
Assert.True(viewModel.Licenses.Count() == 1); // Microsoft.Toolkit.Uwp (CodeBehind)
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == "MVVMLight");
|
||||
viewModel.ProjectSetup.SelectedFramework = viewModel.ProjectSetup.Frameworks.First(pt => pt.Name == testFrameworkName);
|
||||
Assert.True(viewModel.Licenses.Count() == 2); // Added MVVMLight lib
|
||||
await viewModel.ProjectTemplates.InitializeAsync();
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("Settings", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings.MVVMLight").Template));
|
||||
UserSelectionService.AddTemplateAndDependencies(("Settings", FindTemplate(viewModel.ProjectTemplates.PagesGroups, "wts.Page.Settings").Template), testFrameworkName);
|
||||
Assert.True(viewModel.Licenses.Count() == 3); // Added Newtonsoft.Json
|
||||
viewModel.ProjectTemplates.AddTemplateAndDependencies(("HubNotifications", FindTemplate(viewModel.ProjectTemplates.FeatureGroups, "wts.Feat.HubNotifications").Template));
|
||||
UserSelectionService.AddTemplateAndDependencies(("HubNotifications", FindTemplate(viewModel.ProjectTemplates.FeatureGroups, "wts.Feat.HubNotifications").Template), testFrameworkName);
|
||||
Assert.True(viewModel.Licenses.Count() == 4); // Added WindowsAzure.Messaging.Managed
|
||||
viewModel.ProjectTemplates.RemoveTemplate(viewModel.ProjectTemplates.SavedFeatures.First(sf => sf.Identity == "wts.Feat.HubNotifications"), false);
|
||||
UserSelectionService.RemoveTemplate(viewModel.ProjectTemplates.SavedFeatures.First(sf => sf.Identity == "wts.Feat.HubNotifications"));
|
||||
Assert.True(viewModel.Licenses.Count() == 3); // Deleted WindowsAzure.Messaging.Managed
|
||||
}
|
||||
|
||||
|
|
|
@ -98,10 +98,11 @@ The following list shows which tests are executed in which build. Within the Tem
|
|||
* ExecutionSet=BuildCaliburnMicro
|
||||
* ExecutionSet=BuildStyleCop
|
||||
* ExecutionSet=TemplateValidation
|
||||
* ExecutionSet=BuildRightClickWithLegacy
|
||||
|
||||
* VSO 'Templates.Test.Wack' Build (Wack Tests):
|
||||
* Templates.Test
|
||||
* ExecutionSet=ManualOnly
|
||||
* ExecutionSet=LongRunning
|
||||
|
||||
To shorten test execution time traits in Templates.Test are run parallel using this [script](../_build/ParallelTestExecution.ps1).
|
||||
To execute this script locally use the following powershell command:
|
||||
|
|
|
@ -22,8 +22,6 @@ namespace Param_ItemNamespace.ViewModels
|
|||
var data = await SampleDataService.GetSampleModelDataAsync();
|
||||
|
||||
Items.AddRange(data.Select(d => new MasterDetailViewDetailViewModel(d)));
|
||||
|
||||
ActiveItem = Items.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,11 @@
|
|||
Grid.Row="1"
|
||||
x:Name="MasterDetailsViewControl"
|
||||
ItemsSource="{x:Bind ViewModel.Items}"
|
||||
SelectedItem="{x:Bind ViewModel.ActiveItem}"
|
||||
SelectedItem="{x:Bind ViewModel.ActiveItem, Mode=TwoWay}"
|
||||
ItemTemplate="{StaticResource ItemTemplate}"
|
||||
DetailsTemplate="{StaticResource DetailsTemplate}"
|
||||
NoSelectionContentTemplate="{StaticResource NoSelectionContentTemplate}"
|
||||
Loaded="MasterDetailsViewControl_Loaded"
|
||||
BorderBrush="Transparent" />
|
||||
</Grid>
|
||||
</Page>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Microsoft.Toolkit.Uwp.UI.Controls;
|
||||
|
||||
namespace Param_ItemNamespace.Views
|
||||
{
|
||||
|
@ -9,5 +12,13 @@ namespace Param_ItemNamespace.Views
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MasterDetailsViewControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MasterDetailsViewControl.ViewState == MasterDetailsViewState.Both)
|
||||
{
|
||||
ViewModel.ActiveItem = ViewModel.Items.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
|
||||
<Canvas Width="48" Height="48">
|
||||
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#000000">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures="M29.414 4H8V44H40V14.586ZM30 7.414 36.586 14H30ZM10 42V6H28V16H38V42ZM31.106 24.654l-2.344.971a5.877 5.877 0 0 0-1.388-1.388l.971-2.344L26.188 21l-.95 2.293a5.8 5.8 0 0 0-2.219-.049L22.088 21l-2.158.894.911 2.2a5.874 5.874 0 0 0-1.6 1.534l-2.344-.971L16 26.812l2.293.95a5.794 5.794 0 0 0-.049 2.219L16 30.912l.894 2.158 2.2-.911a5.87 5.87 0 0 0 1.749 1.749l-.911 2.2L22.088 37l.93-2.244a5.8 5.8 0 0 0 2.219-.049L26.188 37l2.158-.894-.971-2.344a5.884 5.884 0 0 0 1.534-1.6l2.1.929.975-2.184-2.227-.923a5.794 5.794 0 0 0-.049-2.219L32 26.812ZM24 32.5A3.5 3.5 0 1 1 27.5 29 3.506 3.506 0 0 1 24 32.5Z" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"classifications": [
|
||||
"Universal"
|
||||
],
|
||||
"name": "Settings",
|
||||
"groupIdentity": "wts.Page.Settings",
|
||||
"identity": "wts.Page.Settings.MVVMLight",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"tags": {
|
||||
"language": "C#",
|
||||
"type": "item",
|
||||
"wts.type": "page",
|
||||
"wts.framework": "MVVMLight",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.displayOrder": "2",
|
||||
"wts.dependencies":"wts.Feat.SettingsStorage",
|
||||
"wts.multipleInstance": "false",
|
||||
"wts.genGroup": "1",
|
||||
"wts.rightClickEnabled":"true"
|
||||
},
|
||||
"sourceName": "SettingsPage",
|
||||
"preferNameDirectory": true,
|
||||
"PrimaryOutputs": [
|
||||
{
|
||||
"path": ".\\Helpers\\EnumToBooleanConverter.cs"
|
||||
},
|
||||
{
|
||||
"path": ".\\Views\\SettingsPagePage.xaml"
|
||||
},
|
||||
{
|
||||
"path": ".\\Views\\SettingsPagePage.xaml.cs"
|
||||
},
|
||||
{
|
||||
"path": ".\\ViewModels\\SettingsPageViewModel.cs"
|
||||
},
|
||||
{
|
||||
"path": ".\\Services\\ThemeSelectorService.cs"
|
||||
}
|
||||
],
|
||||
"symbols": {
|
||||
"wts.rootNamespace": {
|
||||
"type": "parameter",
|
||||
"replaces": "Param_RootNamespace"
|
||||
},
|
||||
"wts.itemNamespace": {
|
||||
"type": "parameter",
|
||||
"replaces": "Param_ItemNamespace"
|
||||
},
|
||||
"baseclass": {
|
||||
"type": "parameter",
|
||||
"replaces": "System.ComponentModel.INotifyPropertyChanged"
|
||||
},
|
||||
"setter": {
|
||||
"type": "parameter",
|
||||
"replaces": "Set"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
The settings page is the page where we recommend putting the configuration settings for your application such as setting a dark / light theme. This could also include any licenses, version number and your privacy terms.
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"author": "Microsoft",
|
||||
"name": "Settings",
|
||||
"description": "The settings page is the page where we recommend putting the configuration settings for your app.",
|
||||
"identity": "wts.Page.Settings.MVVMLight"
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace Param_RootNamespace.Helpers
|
||||
{
|
||||
public class EnumToBooleanConverter : IValueConverter
|
||||
{
|
||||
public Type EnumType { get; set; }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (parameter is string enumString)
|
||||
{
|
||||
if (!Enum.IsDefined(EnumType, value))
|
||||
{
|
||||
throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum".GetLocalized());
|
||||
}
|
||||
|
||||
var enumValue = Enum.Parse(EnumType, enumString);
|
||||
|
||||
return enumValue.Equals(value);
|
||||
}
|
||||
|
||||
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName".GetLocalized());
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (parameter is string enumString)
|
||||
{
|
||||
return Enum.Parse(EnumType, enumString);
|
||||
}
|
||||
|
||||
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName".GetLocalized());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
//{**
|
||||
// These code blocks add the ThemeSelectorService initialization to the ActivationService of your project.
|
||||
//**}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
//{[{
|
||||
await ThemeSelectorService.InitializeAsync();
|
||||
//}]}
|
||||
}
|
||||
|
||||
private async Task StartupAsync()
|
||||
{
|
||||
//{[{
|
||||
ThemeSelectorService.SetRequestedTheme();
|
||||
//}]}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
using Param_RootNamespace.Helpers;
|
||||
|
||||
namespace Param_RootNamespace.Services
|
||||
{
|
||||
public static class ThemeSelectorService
|
||||
{
|
||||
private const string SettingsKey = "RequestedTheme";
|
||||
|
||||
public static ElementTheme Theme { get; set; } = ElementTheme.Default;
|
||||
|
||||
public static async Task InitializeAsync()
|
||||
{
|
||||
Theme = await LoadThemeFromSettingsAsync();
|
||||
}
|
||||
|
||||
public static async Task SetThemeAsync(ElementTheme theme)
|
||||
{
|
||||
Theme = theme;
|
||||
|
||||
SetRequestedTheme();
|
||||
await SaveThemeInSettingsAsync(Theme);
|
||||
}
|
||||
|
||||
public static void SetRequestedTheme()
|
||||
{
|
||||
if (Window.Current.Content is FrameworkElement frameworkElement)
|
||||
{
|
||||
frameworkElement.RequestedTheme = Theme;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<ElementTheme> LoadThemeFromSettingsAsync()
|
||||
{
|
||||
ElementTheme cacheTheme = ElementTheme.Default;
|
||||
string themeName = await ApplicationData.Current.LocalSettings.ReadAsync<string>(SettingsKey);
|
||||
|
||||
if (!string.IsNullOrEmpty(themeName))
|
||||
{
|
||||
Enum.TryParse(themeName, out cacheTheme);
|
||||
}
|
||||
|
||||
return cacheTheme;
|
||||
}
|
||||
|
||||
private static async Task SaveThemeInSettingsAsync(ElementTheme theme)
|
||||
{
|
||||
await ApplicationData.Current.LocalSettings.SaveAsync(SettingsKey, theme.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<!--{**-->
|
||||
<!--This xml blocks include string resources for the SettingsPagePage to your project.-->
|
||||
<!--**}-->
|
||||
|
||||
<root>
|
||||
<!--^^-->
|
||||
<!--{[{-->
|
||||
<data name="SettingsPage_Title.Text" xml:space="preserve">
|
||||
<value>SettingsPage</value>
|
||||
<comment>Page title for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_Theme.Text" xml:space="preserve">
|
||||
<value>Choose Theme</value>
|
||||
<comment>Choose theme text for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_Theme_Dark.Content" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
<comment>Dark theme text for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_Theme_Default.Content" xml:space="preserve">
|
||||
<value>Windows default</value>
|
||||
<comment>Windows default theme text for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_Theme_Light.Content" xml:space="preserve">
|
||||
<value>Light</value>
|
||||
<comment>Light theme text for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_About.Text" xml:space="preserve">
|
||||
<value>About this application</value>
|
||||
<comment>About this application title for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_AboutDescription.Text" xml:space="preserve">
|
||||
<value>Settings page placeholder text. Your app description goes here.</value>
|
||||
<comment>About this application description for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_PrivacyTermsLink.Content" xml:space="preserve">
|
||||
<value>Privacy Statement</value>
|
||||
<comment>Privacy Statement link content for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_PrivacyTermsLink.NavigateUri" xml:space="preserve">
|
||||
<value>https://YourPrivacyUrlGoesHere/</value>
|
||||
<comment>Here is your Privacy Statement url for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="SettingsPage_Personalization.Text" xml:space="preserve">
|
||||
<value>Personalization</value>
|
||||
<comment>Personalization text for SettingsPage</comment>
|
||||
</data>
|
||||
<data name="ExceptionEnumToBooleanConverterValueMustBeAnEnum" xml:space="preserve">
|
||||
<value>value must be an Enum!</value>
|
||||
<comment>Value must be an Enum in enum to boolean converter</comment>
|
||||
</data>
|
||||
<data name="ExceptionEnumToBooleanConverterParameterMustBeAnEnumName" xml:space="preserve">
|
||||
<value>parameter must be an Enum name!</value>
|
||||
<comment>Parameter must be an Enum name in enum to boolean converter</comment>
|
||||
</data>
|
||||
NavigateUri
|
||||
<!--}]}-->
|
||||
</root>
|
|
@ -1,67 +0,0 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
using Param_RootNamespace.Services;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace Param_ItemNamespace.ViewModels
|
||||
{
|
||||
public class SettingsPageViewModel : System.ComponentModel.INotifyPropertyChanged
|
||||
{
|
||||
// TODO WTS: Add other settings as necessary. For help see https://github.com/Microsoft/WindowsTemplateStudio/blob/master/docs/pages/settings.md
|
||||
private ElementTheme _elementTheme = ThemeSelectorService.Theme;
|
||||
|
||||
public ElementTheme ElementTheme
|
||||
{
|
||||
get { return _elementTheme; }
|
||||
|
||||
set { Set(ref _elementTheme, value); }
|
||||
}
|
||||
|
||||
private string _versionDescription;
|
||||
|
||||
public string VersionDescription
|
||||
{
|
||||
get { return _versionDescription; }
|
||||
|
||||
set { Set(ref _versionDescription, value); }
|
||||
}
|
||||
|
||||
private ICommand _switchThemeCommand;
|
||||
|
||||
public ICommand SwitchThemeCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_switchThemeCommand == null)
|
||||
{
|
||||
_switchThemeCommand = new RelayCommand<ElementTheme>(
|
||||
async (param) =>
|
||||
{
|
||||
await ThemeSelectorService.SetThemeAsync(param);
|
||||
});
|
||||
}
|
||||
|
||||
return _switchThemeCommand;
|
||||
}
|
||||
}
|
||||
|
||||
public SettingsPageViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
VersionDescription = GetVersionDescription();
|
||||
}
|
||||
|
||||
private string GetVersionDescription()
|
||||
{
|
||||
var package = Package.Current;
|
||||
var packageId = package.Id;
|
||||
var version = packageId.Version;
|
||||
|
||||
return $"{package.DisplayName} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
<Page
|
||||
x:Class="Param_ItemNamespace.Views.SettingsPagePage"
|
||||
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:helper="using:Param_ItemNamespace.Helpers"
|
||||
xmlns:xaml="using:Windows.UI.Xaml"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<helper:EnumToBooleanConverter x:Key="EnumToBooleanConverter" EnumType="ElementTheme" />
|
||||
</Page.Resources>
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid Margin="{StaticResource MediumLeftRightMargin}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="48"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
x:Uid="SettingsPage_Title"
|
||||
x:Name="TitlePage"
|
||||
Style="{StaticResource PageTitleStyle}" />
|
||||
|
||||
<StackPanel Grid.Row="1">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPage_Personalization"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}" />
|
||||
|
||||
<StackPanel Margin="{StaticResource SettingsSubheaderMargin}">
|
||||
<TextBlock
|
||||
x:Uid="SettingsPage_Theme"
|
||||
Style="{StaticResource BodyTextStyle}" />
|
||||
|
||||
<StackPanel Margin="{StaticResource EightTopMargin}">
|
||||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Light"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{Binding ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Light, Mode=TwoWay}"
|
||||
Command="{Binding SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Light</xaml:ElementTheme>
|
||||
</RadioButton.CommandParameter>
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Dark"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{Binding ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Dark, Mode=TwoWay}"
|
||||
Command="{Binding SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Dark</xaml:ElementTheme>
|
||||
</RadioButton.CommandParameter>
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Default"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{Binding ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Default, Mode=TwoWay}"
|
||||
Command="{Binding SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Default</xaml:ElementTheme>
|
||||
</RadioButton.CommandParameter>
|
||||
</RadioButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
x:Uid="SettingsPage_About"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"/>
|
||||
|
||||
<StackPanel Margin="{StaticResource EightTopMargin}">
|
||||
<TextBlock
|
||||
Text="{x:Bind ViewModel.VersionDescription, Mode=OneWay}" />
|
||||
<TextBlock
|
||||
x:Uid="SettingsPage_AboutDescription"
|
||||
Margin="{StaticResource EightTopMargin}" />
|
||||
|
||||
<HyperlinkButton
|
||||
x:Uid="SettingsPage_PrivacyTermsLink"
|
||||
Margin="{StaticResource EightTopMargin}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace Param_ItemNamespace.Views
|
||||
{
|
||||
public sealed partial class SettingsPagePage : Page
|
||||
{
|
||||
//// TODO WTS: Change the URL for your privacy policy in the Resource File, currently set to https://YourPrivacyUrlGoesHere
|
||||
|
||||
public SettingsPagePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
"language": "C#",
|
||||
"type": "item",
|
||||
"wts.type": "page",
|
||||
"wts.framework": "MVVMBasic",
|
||||
"wts.framework": "MVVMBasic|MVVMLight",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.displayOrder": "2",
|
||||
"wts.dependencies":"wts.Feat.SettingsStorage",
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Param_ItemNamespace.ViewModels
|
|||
_switchThemeCommand = new RelayCommand<ElementTheme>(
|
||||
async (param) =>
|
||||
{
|
||||
ElementTheme = param;
|
||||
await ThemeSelectorService.SetThemeAsync(param);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Light"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Light, Mode=TwoWay}"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Light, Mode=OneWay}"
|
||||
Command="{x:Bind ViewModel.SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Light</xaml:ElementTheme>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Dark"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Dark, Mode=TwoWay}"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Dark, Mode=OneWay}"
|
||||
Command="{x:Bind ViewModel.SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Dark</xaml:ElementTheme>
|
||||
|
@ -55,7 +55,7 @@
|
|||
<RadioButton
|
||||
x:Uid="SettingsPage_Theme_Default"
|
||||
GroupName="AppTheme"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Default, Mode=TwoWay}"
|
||||
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Default, Mode=OneWay}"
|
||||
Command="{x:Bind ViewModel.SwitchThemeCommand}">
|
||||
<RadioButton.CommandParameter>
|
||||
<xaml:ElementTheme>Default</xaml:ElementTheme>
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
This is a generic version of a MVVM pattern. The [Model-View-ViewModel pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) can be used on all XAML platforms. Its intent is to provide a clean separation of concerns between the user interface controls and their logic.
|
||||
|
||||
There are three core components in the MVVM pattern: the model, the view, and the view model. Each serves a distinct and separate role.
|
||||
|
||||
MVVM Basic is not a framework but provides the minimum functionality to create an app using the Model-View-ViewModel (MVVM) pattern.
|
||||
Use it if you can't or don't want to use a 3rd party MVVM Framework.
|
||||
|
||||
MVVM Basic is not intended to be a fully features MVVM Framework and does not include some features that other frameworks do. ViewModel-first navigation, IOC, and messaging being the most obvious ones. If you want these features then choose a framework that supports them.
|
||||
|
||||
Projects created with MVVM Basic contain two important classes, `Observable` and `RelayCommand`.
|
||||
**Observable** contains an implementation of the `INotifyPropertyChanged` interface and is used as a base class for all view models. This makes it easy to update bound properties on the View.
|
||||
**RelayCommand** contains an implementation of the `ICommand` interface to make it easy to have the View call commands on the ViewModel, rather than handle UI events directly.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMLight & identity == wts.Page.Settings.MVVMLight|wts.Page.Camera"
|
||||
"wts.compositionFilter": "$framework == MVVMLight & identity == wts.Page.Settings|wts.Page.Camera"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMLight & identity == wts.Page.Settings.MVVMLight|wts.Page.Camera"
|
||||
"wts.compositionFilter": "$framework == MVVMLight & identity == wts.Page.Settings|wts.Page.Camera"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "wts.type == page & identity != wts.Page.Settings.MVVMLight & $framework == MVVMLight & $projectType == SplitView"
|
||||
"wts.compositionFilter": "wts.type == page & identity != wts.Page.Settings & $framework == MVVMLight & $projectType == SplitView"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "wts.type == page & identity != wts.Page.Settings.MVVMLight & $framework == MVVMLight & $projectType == SplitView",
|
||||
"wts.compositionFilter": "wts.type == page & identity != wts.Page.Settings & $framework == MVVMLight & $projectType == SplitView",
|
||||
"wts.compositionOrder": "2"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMLight & $projectType == SplitView & identity == wts.Page.Settings.MVVMLight"
|
||||
"wts.compositionFilter": "$framework == MVVMLight & $projectType == SplitView & identity == wts.Page.Settings"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMLight & $projectType == SplitView & identity == wts.Page.Settings.MVVMLight",
|
||||
"wts.compositionFilter": "$framework == MVVMLight & $projectType == SplitView & identity == wts.Page.Settings",
|
||||
"wts.compositionOrder": "3"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMBasic|MVVMLight & $projectType == Blank|SplitView & identity == wts.Page.Settings|wts.Page.Settings.MVVMLight"
|
||||
"wts.compositionFilter": "$framework == MVVMBasic|MVVMLight & $projectType == Blank|SplitView & identity == wts.Page.Settings"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$framework == MVVMBasic|MVVMLight & $projectType == TabbedPivot & identity == wts.Page.Settings|wts.Page.Settings.MVVMLight"
|
||||
"wts.compositionFilter": "$framework == MVVMBasic|MVVMLight & $projectType == TabbedPivot & identity == wts.Page.Settings"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"type": "item",
|
||||
"wts.type": "composition",
|
||||
"wts.version": "1.0.0",
|
||||
"wts.compositionFilter": "$projectType == SplitView & groupidentity == wts.Page.Blank|wts.Page.Settings|wts.Page.Settings.MVVMLight|wts.Page.TabbedPivot|wts.Page.Chart|wts.Page.ImageGallery|wts.Page.MasterDetail|wts.Page.Camera"
|
||||
"wts.compositionFilter": "$projectType == SplitView & groupidentity == wts.Page.Blank|wts.Page.Settings|wts.Page.TabbedPivot|wts.Page.Chart|wts.Page.ImageGallery|wts.Page.MasterDetail|wts.Page.Camera"
|
||||
},
|
||||
"sourceName": "wts.ItemName",
|
||||
"preferNameDirectory": true,
|
||||
|
|
Загрузка…
Ссылка в новой задаче