Merge branch 'dev' into Issue36-doc

This commit is contained in:
Martin Vega 2017-10-09 08:53:09 +02:00
Родитель a726a1a5f8 69ac70960d
Коммит e60ad1e7f4
79 изменённых файлов: 687 добавлений и 800 удалений

Просмотреть файл

@ -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,