Added in generic ViewModel

This commit is contained in:
Clint Rutkas
2020-03-11 10:43:32 -07:00
committed by Lavius Motileng
parent e2c7941542
commit 3f5a54f9f1
43 changed files with 1305 additions and 23 deletions

View File

@@ -1,6 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace settingsUintTests
namespace Microsoft.PowerToys.Settings.Test
{
[TestClass]
public class UnitTest1

View File

@@ -1,7 +1,6 @@
<Application x:Class="SettingsRunner.App"
<Application x:Class="Microsoft.PowerToys.Settings.UI.Runner.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SettingsRunner"
StartupUri="MainWindow.xaml">
<Application.Resources>

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace SettingsRunner
namespace Microsoft.PowerToys.Settings.UI.Runner
{
/// <summary>
/// Interaction logic for App.xaml

View File

@@ -1,16 +1,17 @@
<Window x:Class="SettingsRunner.MainWindow"
<Window x:Class="Microsoft.PowerToys.Settings.UI.Runner.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SettingsRunner"
xmlns:local="clr-namespace:Microsoft.PowerToys.Settings.UI.Runner"
xmlns:Controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
xmlns:xaml="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
mc:Ignorable="d"
Title="PowerToys Settings" Height="800" Width="800">
<Grid>
<xaml:WindowsXamlHost InitialTypeName="Microsoft.PowerToys.Settings.UI.Controls.DummyUserControl" ChildChanged="WindowsXamlHost_ChildChanged" />
<!--<xaml:WindowsXamlHost InitialTypeName="Microsoft.PowerToys.Settings.UI.Controls.DummyUserControl" ChildChanged="WindowsXamlHost_ChildChanged" />-->
<xaml:WindowsXamlHost InitialTypeName="Microsoft.PowerToys.Settings.UI.Views.ShellPage" ChildChanged="WindowsXamlHost_ChildChanged" />
</Grid>
</Window>

View File

@@ -2,8 +2,9 @@
using System.Windows;
using Microsoft.Toolkit.Wpf.UI.XamlHost;
using Microsoft.PowerToys.Settings.UI.Controls;
using Microsoft.PowerToys.Settings.UI.Views;
namespace SettingsRunner
namespace Microsoft.PowerToys.Settings.UI.Runner
{
/// <summary>
/// Interaction logic for MainWindow.xaml
@@ -19,11 +20,11 @@ namespace SettingsRunner
{
// Hook up x:Bind source.
WindowsXamlHost windowsXamlHost = sender as WindowsXamlHost;
DummyUserControl userControl = windowsXamlHost.GetUwpInternalObject() as DummyUserControl;
ShellPage userControl = windowsXamlHost.GetUwpInternalObject() as ShellPage;
if (userControl != null)
{
userControl.XamlIslandMessage = this.WPFMessage;
//userControl.XamlIslandMessage = this.WPFMessage;
}
}

View File

@@ -4,7 +4,7 @@
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
<StartupObject>SettingsRunner.Program</StartupObject>
<StartupObject>Microsoft.PowerToys.Settings.UI.Runner.Program</StartupObject>
<Authors>Microsoft Corporation</Authors>
<Product>PowerToys</Product>
<Description>Windows system utilities to maximize productivity</Description>
@@ -18,6 +18,9 @@
<Platforms>x64</Platforms>
<ApplicationIcon>icon.ico</ApplicationIcon>
<Win32Resource />
<!-- crutkas TODO: added for fallback, may need to be removed for WinUI3 -->
<AssetTargetFallback>uap10.0.18362</AssetTargetFallback>
</PropertyGroup>
<ItemGroup>

View File

@@ -2,16 +2,16 @@
using System.Collections.Generic;
using System.Text;
namespace SettingsRunner
namespace Microsoft.PowerToys.Settings.UI.Runner
{
public class Program
{
[System.STAThreadAttribute()]
public static void Main()
{
using (new SettingsUI.App())
using (new UI.App())
{
SettingsRunner.App app = new SettingsRunner.App();
App app = new App();
app.InitializeComponent();
app.Run();
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Activation
{
// For more information on understanding and extending activation flow see
// https://github.com/Microsoft/WindowsTemplateStudio/blob/master/docs/activation.md
internal abstract class ActivationHandler
{
public abstract bool CanHandle(object args);
public abstract Task HandleAsync(object args);
}
// Extend this class to implement new ActivationHandlers
internal abstract class ActivationHandler<T> : ActivationHandler
where T : class
{
// Override this method to add the activation logic in your activation handler
protected abstract Task HandleInternalAsync(T args);
public override async Task HandleAsync(object args)
{
await HandleInternalAsync(args as T);
}
public override bool CanHandle(object args)
{
// CanHandle checks the args is of type you have configured
return args is T && CanHandleInternal(args as T);
}
// You can override this method to add extra validation on activation args
// to determine if your ActivationHandler should handle this activation args
protected virtual bool CanHandleInternal(T args)
{
return true;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Services;
using Windows.ApplicationModel.Activation;
namespace Microsoft.PowerToys.Settings.UI.Activation
{
internal class DefaultActivationHandler : ActivationHandler<IActivatedEventArgs>
{
private readonly Type _navElement;
public DefaultActivationHandler(Type navElement)
{
_navElement = navElement;
}
protected override async Task HandleInternalAsync(IActivatedEventArgs args)
{
// When the navigation stack isn't restored, navigate to the first page and configure
// the new page by passing required information in the navigation parameter
object arguments = null;
if (args is LaunchActivatedEventArgs launchArgs)
{
arguments = launchArgs.Arguments;
}
NavigationService.Navigate(_navElement, arguments);
await Task.CompletedTask;
}
protected override bool CanHandleInternal(IActivatedEventArgs args)
{
// None of the ActivationHandlers has handled the app activation
return NavigationService.Frame.Content == null && _navElement != null;
}
}
}

View File

@@ -1,10 +1,19 @@
<xaml:XamlApplication
x:Class="SettingsUI.App"
x:Class="Microsoft.PowerToys.Settings.UI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xaml="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:local="using:SettingsUI">
xmlns:xaml="using:Microsoft.Toolkit.Win32.UI.XamlHost">
<Application.Resources>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary Source="/Styles/_Colors.xaml" />
<ResourceDictionary Source="/Styles/_FontSizes.xaml" />
<ResourceDictionary Source="/Styles/_Thickness.xaml" />
<ResourceDictionary Source="/Styles/TextBlock.xaml" />
<ResourceDictionary Source="/Styles/Page.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</xaml:XamlApplication>

View File

@@ -1,6 +1,6 @@
using Microsoft.Toolkit.Win32.UI.XamlHost;
namespace SettingsUI
namespace Microsoft.PowerToys.Settings.UI
{
public sealed partial class App : XamlApplication
{
@@ -8,5 +8,7 @@ namespace SettingsUI
{
this.Initialize();
}
}
}

View File

@@ -0,0 +1,134 @@
using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using WinUI = Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Behaviors
{
public class NavigationViewHeaderBehavior : Behavior<WinUI.NavigationView>
{
private static NavigationViewHeaderBehavior _current;
private Page _currentPage;
public DataTemplate DefaultHeaderTemplate { get; set; }
public object DefaultHeader
{
get { return GetValue(DefaultHeaderProperty); }
set { SetValue(DefaultHeaderProperty, value); }
}
public static readonly DependencyProperty DefaultHeaderProperty = DependencyProperty.Register("DefaultHeader", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current.UpdateHeader()));
public static NavigationViewHeaderMode GetHeaderMode(Page item)
{
return (NavigationViewHeaderMode)item.GetValue(HeaderModeProperty);
}
public static void SetHeaderMode(Page item, NavigationViewHeaderMode value)
{
item.SetValue(HeaderModeProperty, value);
}
public static readonly DependencyProperty HeaderModeProperty =
DependencyProperty.RegisterAttached("HeaderMode", typeof(bool), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(NavigationViewHeaderMode.Always, (d, e) => _current.UpdateHeader()));
public static object GetHeaderContext(Page item)
{
return item.GetValue(HeaderContextProperty);
}
public static void SetHeaderContext(Page item, object value)
{
item.SetValue(HeaderContextProperty, value);
}
public static readonly DependencyProperty HeaderContextProperty =
DependencyProperty.RegisterAttached("HeaderContext", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current.UpdateHeader()));
public static DataTemplate GetHeaderTemplate(Page item)
{
return (DataTemplate)item.GetValue(HeaderTemplateProperty);
}
public static void SetHeaderTemplate(Page item, DataTemplate value)
{
item.SetValue(HeaderTemplateProperty, value);
}
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.RegisterAttached("HeaderTemplate", typeof(DataTemplate), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current.UpdateHeaderTemplate()));
protected override void OnAttached()
{
base.OnAttached();
_current = this;
NavigationService.Navigated += OnNavigated;
}
protected override void OnDetaching()
{
base.OnDetaching();
NavigationService.Navigated -= OnNavigated;
}
private void OnNavigated(object sender, NavigationEventArgs e)
{
var frame = sender as Frame;
if (frame.Content is Page page)
{
_currentPage = page;
UpdateHeader();
UpdateHeaderTemplate();
}
}
private void UpdateHeader()
{
if (_currentPage != null)
{
var headerMode = GetHeaderMode(_currentPage);
if (headerMode == NavigationViewHeaderMode.Never)
{
AssociatedObject.Header = null;
AssociatedObject.AlwaysShowHeader = false;
}
else
{
var headerFromPage = GetHeaderContext(_currentPage);
if (headerFromPage != null)
{
AssociatedObject.Header = headerFromPage;
}
else
{
AssociatedObject.Header = DefaultHeader;
}
if (headerMode == NavigationViewHeaderMode.Always)
{
AssociatedObject.AlwaysShowHeader = true;
}
else
{
AssociatedObject.AlwaysShowHeader = false;
}
}
}
}
private void UpdateHeaderTemplate()
{
if (_currentPage != null)
{
var headerTemplate = GetHeaderTemplate(_currentPage);
AssociatedObject.HeaderTemplate = headerTemplate ?? DefaultHeaderTemplate;
}
}
}
}

View File

@@ -0,0 +1,9 @@
namespace Microsoft.PowerToys.Settings.UI.Behaviors
{
public enum NavigationViewHeaderMode
{
Always,
Never,
Minimal
}
}

View File

@@ -0,0 +1,31 @@
using System;
using Microsoft.UI.Xaml.Controls;
using Windows.UI.Xaml;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public class NavHelper
{
// This helper class allows to specify the page that will be shown when you click on a NavigationViewItem
//
// Usage in xaml:
// <winui:NavigationViewItem x:Uid="Shell_Main" Icon="Document" helpers:NavHelper.NavigateTo="views:MainPage" />
//
// Usage in code:
// NavHelper.SetNavigateTo(navigationViewItem, typeof(MainPage));
public static Type GetNavigateTo(NavigationViewItem item)
{
return (Type)item.GetValue(NavigateToProperty);
}
public static void SetNavigateTo(NavigationViewItem item, Type value)
{
item.SetValue(NavigateToProperty, value);
}
public static readonly DependencyProperty NavigateToProperty =
DependencyProperty.RegisterAttached("NavigateTo", typeof(Type), typeof(NavHelper), new PropertyMetadata(null));
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public class Observable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Windows.Input;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
public void Execute(object parameter) => _execute();
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public class RelayCommand<T> : ICommand
{
private readonly Action<T> _execute;
private readonly Func<T, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);
public void Execute(object parameter) => _execute((T)parameter);
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Runtime.InteropServices;
using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
internal static class ResourceExtensions
{
private static ResourceLoader _resLoader = new ResourceLoader();
public static string GetLocalized(this string resourceKey)
{
return _resLoader.GetString(resourceKey);
}
}
}

View File

@@ -116,13 +116,43 @@
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="Activation\ActivationHandler.cs" />
<Compile Include="Activation\DefaultActivationHandler.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Behaviors\NavigationViewHeaderBehavior.cs" />
<Compile Include="Behaviors\NavigationViewHeaderMode.cs" />
<Compile Include="Controls\DummyUserControl.xaml.cs">
<DependentUpon>DummyUserControl.xaml</DependentUpon>
</Compile>
<Compile Include="Helpers\NavHelper.cs" />
<Compile Include="Helpers\Observable.cs" />
<Compile Include="Helpers\RelayCommand.cs" />
<Compile Include="Helpers\ResourceExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\ActivationService.cs" />
<Compile Include="Services\NavigationService.cs" />
<Compile Include="ViewModels\MainViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\Test1ViewModel.cs" />
<Compile Include="ViewModels\Test2ViewModel.cs" />
<Compile Include="ViewModels\Test3ViewModel.cs" />
<Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ShellPage.xaml.cs">
<DependentUpon>ShellPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Test1Page.xaml.cs">
<DependentUpon>Test1Page.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Test2Page.xaml.cs">
<DependentUpon>Test2Page.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Test3Page.xaml.cs">
<DependentUpon>Test3Page.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
@@ -150,13 +180,58 @@
<PackageReference Include="Microsoft.UI.Xaml">
<Version>2.4.0-prerelease.191217001</Version>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
<Version>2.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PRIResource Include="Strings\en-us\Resources.resw" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Page Include="Controls\DummyUserControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\Page.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\TextBlock.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\_Colors.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\_FontSizes.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\_Thickness.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ShellPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Test1Page.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Test2Page.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Test3Page.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>

View File

@@ -30,7 +30,7 @@
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="settingsui.App">
EntryPoint="Microsoft.PowerToys.Settings.UI.App">
<uap:VisualElements
DisplayName="PowerToys"
Description="Windows system utilities to maximize productivity"

View File

@@ -5,11 +5,11 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("settingsui")]
[assembly: AssemblyTitle("Microsoft.PowerToys.Settings.UI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("settingsui")]
[assembly: AssemblyProduct("Microsoft.PowerToys.Settings.UI")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Activation;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Services
{
// For more information on understanding and extending activation flow see
// https://github.com/Microsoft/WindowsTemplateStudio/blob/master/docs/activation.md
internal class ActivationService
{
private readonly App _app;
private readonly Type _defaultNavItem;
private Lazy<UIElement> _shell;
private object _lastActivationArgs;
public ActivationService(App app, Type defaultNavItem, Lazy<UIElement> shell = null)
{
_app = app;
_shell = shell;
_defaultNavItem = defaultNavItem;
}
public async Task ActivateAsync(object activationArgs)
{
if (IsInteractive(activationArgs))
{
// Initialize services that you need before app activation
// take into account that the splash screen is shown while this code runs.
await InitializeAsync();
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (Window.Current.Content == null)
{
// Create a Shell or Frame to act as the navigation context
Window.Current.Content = _shell?.Value ?? new Frame();
}
}
// Depending on activationArgs one of ActivationHandlers or DefaultActivationHandler
// will navigate to the first page
await HandleActivationAsync(activationArgs);
_lastActivationArgs = activationArgs;
if (IsInteractive(activationArgs))
{
// Ensure the current window is active
Window.Current.Activate();
// Tasks after activation
await StartupAsync();
}
}
private async Task InitializeAsync()
{
await Task.CompletedTask;
}
private async Task HandleActivationAsync(object activationArgs)
{
var activationHandler = GetActivationHandlers()
.FirstOrDefault(h => h.CanHandle(activationArgs));
if (activationHandler != null)
{
await activationHandler.HandleAsync(activationArgs);
}
if (IsInteractive(activationArgs))
{
var defaultHandler = new DefaultActivationHandler(_defaultNavItem);
if (defaultHandler.CanHandle(activationArgs))
{
await defaultHandler.HandleAsync(activationArgs);
}
}
}
private async Task StartupAsync()
{
await Task.CompletedTask;
}
private IEnumerable<ActivationHandler> GetActivationHandlers()
{
yield break;
}
private bool IsInteractive(object args)
{
return args is IActivatedEventArgs;
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.Services
{
public static class NavigationService
{
public static event NavigatedEventHandler Navigated;
public static event NavigationFailedEventHandler NavigationFailed;
private static Frame _frame;
private static object _lastParamUsed;
public static Frame Frame
{
get
{
if (_frame == null)
{
_frame = Window.Current.Content as Frame;
RegisterFrameEvents();
}
return _frame;
}
set
{
UnregisterFrameEvents();
_frame = value;
RegisterFrameEvents();
}
}
public static bool CanGoBack => Frame.CanGoBack;
public static bool CanGoForward => Frame.CanGoForward;
public static bool GoBack()
{
if (CanGoBack)
{
Frame.GoBack();
return true;
}
return false;
}
public static void GoForward() => Frame.GoForward();
public static bool Navigate(Type pageType, object parameter = null, NavigationTransitionInfo infoOverride = null)
{
// Don't open the same page multiple times
if (Frame.Content?.GetType() != pageType || (parameter != null && !parameter.Equals(_lastParamUsed)))
{
var navigationResult = Frame.Navigate(pageType, parameter, infoOverride);
if (navigationResult)
{
_lastParamUsed = parameter;
}
return navigationResult;
}
else
{
return false;
}
}
public static bool Navigate<T>(object parameter = null, NavigationTransitionInfo infoOverride = null)
where T : Page
=> Navigate(typeof(T), parameter, infoOverride);
private static void RegisterFrameEvents()
{
if (_frame != null)
{
_frame.Navigated += Frame_Navigated;
_frame.NavigationFailed += Frame_NavigationFailed;
}
}
private static void UnregisterFrameEvents()
{
if (_frame != null)
{
_frame.Navigated -= Frame_Navigated;
_frame.NavigationFailed -= Frame_NavigationFailed;
}
}
private static void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e) => NavigationFailed?.Invoke(sender, e);
private static void Frame_Navigated(object sender, NavigationEventArgs e) => Navigated?.Invoke(sender, e);
}
}

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDisplayName" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application display name</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application description</comment>
</data>
<data name="Shell_Main.Content" xml:space="preserve">
<value>Main</value>
<comment>Navigation view item name for Main</comment>
</data>
<data name="Shell_Test1.Content" xml:space="preserve">
<value>Test1</value>
<comment>Navigation view item name for Test1</comment>
</data>
<data name="Shell_Test2.Content" xml:space="preserve">
<value>Test2</value>
<comment>Navigation view item name for Test2</comment>
</data>
<data name="Shell_Test3.Content" xml:space="preserve">
<value>Test3</value>
<comment>Navigation view item name for Test3</comment>
</data>
</root>

View File

@@ -0,0 +1,9 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Page" x:Key="PageStyle">
<Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,21 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--Common texts-->
<Style x:Key="PageTitleStyle" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontWeight" Value="SemiLight" />
<Setter Property="FontSize" Value="{StaticResource LargeFontSize}" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap" />
</Style>
<Style x:Key="BodyTextStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{StaticResource MediumFontSize}" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,5 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="ThemeControlForegroundBaseHighBrush" Color="{ThemeResource SystemBaseHighColor}"></SolidColorBrush>
</ResourceDictionary>

View File

@@ -0,0 +1,8 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<x:Double x:Key="LargeFontSize">24</x:Double>
<x:Double x:Key="MediumFontSize">16</x:Double>
</ResourceDictionary>

View File

@@ -0,0 +1,30 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--Medium size margins-->
<Thickness x:Key="MediumLeftMargin">24,0,0,0</Thickness>
<Thickness x:Key="MediumTopMargin">0,24,0,0</Thickness>
<Thickness x:Key="MediumLeftRightMargin">24,0,24,0</Thickness>
<Thickness x:Key="MediumRightMargin">0,0,24,0</Thickness>
<Thickness x:Key="MediumTopBottomMargin">0,24,0,24</Thickness>
<Thickness x:Key="MediumLeftTopRightBottomMargin">24,24,24,24</Thickness>
<Thickness x:Key="MediumBottomMargin">0,0,0,24</Thickness>
<!--Small size margins-->
<Thickness x:Key="SmallLeftMargin">12, 0, 0, 0</Thickness>
<Thickness x:Key="SmallTopMargin">0, 12, 0, 0</Thickness>
<Thickness x:Key="SmallTopBottomMargin">0, 12, 0, 12</Thickness>
<Thickness x:Key="SmallLeftRightMargin">12, 0, 12, 0</Thickness>
<Thickness x:Key="SmallRightMargin">0, 0, 12, 0</Thickness>
<Thickness x:Key="SmallLeftTopRightBottomMargin">12, 12, 12, 12</Thickness>
<!--Extra Small size margins-->
<Thickness x:Key="XSmallLeftMargin">8, 0, 0, 0</Thickness>
<Thickness x:Key="XSmallTopMargin">0, 8, 0, 0</Thickness>
<Thickness x:Key="XSmallLeftTopRightBottomMargin">8, 8, 8, 8</Thickness>
<!--Extra Extra Small size margins-->
<Thickness x:Key="XXSmallTopMargin">0, 4, 0, 0</Thickness>
<Thickness x:Key="XXSmallTopRightBottomMargin">0, 4, 4, 4</Thickness>
</ResourceDictionary>

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.PowerToys.Settings.UI.Helpers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class MainViewModel : Observable
{
public MainViewModel()
{
}
}
}

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Services;
using Windows.System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
using WinUI = Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class ShellViewModel : Observable
{
private readonly KeyboardAccelerator _altLeftKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu);
private readonly KeyboardAccelerator _backKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.GoBack);
private bool _isBackEnabled;
private IList<KeyboardAccelerator> _keyboardAccelerators;
private WinUI.NavigationView _navigationView;
private WinUI.NavigationViewItem _selected;
private ICommand _loadedCommand;
private ICommand _itemInvokedCommand;
public bool IsBackEnabled
{
get { return _isBackEnabled; }
set { Set(ref _isBackEnabled, value); }
}
public WinUI.NavigationViewItem Selected
{
get { return _selected; }
set { Set(ref _selected, value); }
}
public ICommand LoadedCommand => _loadedCommand ?? (_loadedCommand = new RelayCommand(OnLoaded));
public ICommand ItemInvokedCommand => _itemInvokedCommand ?? (_itemInvokedCommand = new RelayCommand<WinUI.NavigationViewItemInvokedEventArgs>(OnItemInvoked));
public ShellViewModel()
{
}
public void Initialize(Frame frame, WinUI.NavigationView navigationView, IList<KeyboardAccelerator> keyboardAccelerators)
{
_navigationView = navigationView;
_keyboardAccelerators = keyboardAccelerators;
NavigationService.Frame = frame;
NavigationService.NavigationFailed += Frame_NavigationFailed;
NavigationService.Navigated += Frame_Navigated;
_navigationView.BackRequested += OnBackRequested;
}
private async void OnLoaded()
{
// Keyboard accelerators are added here to avoid showing 'Alt + left' tooltip on the page.
// More info on tracking issue https://github.com/Microsoft/microsoft-ui-xaml/issues/8
_keyboardAccelerators.Add(_altLeftKeyboardAccelerator);
_keyboardAccelerators.Add(_backKeyboardAccelerator);
await Task.CompletedTask;
}
private void OnItemInvoked(WinUI.NavigationViewItemInvokedEventArgs args)
{
var item = _navigationView.MenuItems
.OfType<WinUI.NavigationViewItem>()
.First(menuItem => (string)menuItem.Content == (string)args.InvokedItem);
var pageType = item.GetValue(NavHelper.NavigateToProperty) as Type;
NavigationService.Navigate(pageType);
}
private void OnBackRequested(WinUI.NavigationView sender, WinUI.NavigationViewBackRequestedEventArgs args)
{
NavigationService.GoBack();
}
private void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw e.Exception;
}
private void Frame_Navigated(object sender, NavigationEventArgs e)
{
IsBackEnabled = NavigationService.CanGoBack;
Selected = _navigationView.MenuItems
.OfType<WinUI.NavigationViewItem>()
.FirstOrDefault(menuItem => IsMenuItemForPageType(menuItem, e.SourcePageType));
}
private bool IsMenuItemForPageType(WinUI.NavigationViewItem menuItem, Type sourcePageType)
{
var pageType = menuItem.GetValue(NavHelper.NavigateToProperty) as Type;
return pageType == sourcePageType;
}
private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null)
{
var keyboardAccelerator = new KeyboardAccelerator() { Key = key };
if (modifiers.HasValue)
{
keyboardAccelerator.Modifiers = modifiers.Value;
}
keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked;
return keyboardAccelerator;
}
private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
var result = NavigationService.GoBack();
args.Handled = result;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.PowerToys.Settings.UI.Helpers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class Test1ViewModel : Observable
{
public Test1ViewModel()
{
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.PowerToys.Settings.UI.Helpers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class Test2ViewModel : Observable
{
public Test2ViewModel()
{
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.PowerToys.Settings.UI.Helpers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class Test3ViewModel : Observable
{
public Test3ViewModel()
{
}
}
}

View File

@@ -0,0 +1,18 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.MainPage"
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"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,18 @@
using System;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class MainPage : Page
{
public MainViewModel ViewModel { get; } = new MainViewModel();
public MainPage()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,81 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Views.ShellPage"
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:behaviors="using:Microsoft.PowerToys.Settings.UI.Behaviors"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
xmlns:helpers="using:Microsoft.PowerToys.Settings.UI.Helpers"
xmlns:views="using:Microsoft.PowerToys.Settings.UI.Views"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:i="using:Microsoft.Xaml.Interactivity"
mc:Ignorable="d">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="Loaded">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.LoadedCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<!--
TODO:
Style clean up for navview
-->
<winui:NavigationView
x:Name="navigationView"
IsBackButtonVisible="Collapsed"
IsBackEnabled="{x:Bind ViewModel.IsBackEnabled, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"
IsSettingsVisible="False"
IsPaneToggleButtonVisible="False"
PaneDisplayMode="Left"
Background="{ThemeResource SystemControlBackgroundAltHighBrush}">
<winui:NavigationView.PaneHeader>
<!--
TODO:
PowerToys needs to be string
Think maybe about svg logo here
Margin should be style
-->
<TextBlock Margin="12, 24, 0, 6" Style="{StaticResource SubheaderTextBlockStyle}" FontWeight="Bold">PowerToys</TextBlock>
</winui:NavigationView.PaneHeader>
<winui:NavigationView.MenuItems>
<!--
TODO WTS: Change the symbols for each item as appropriate for your app
More on Segoe UI Symbol icons: https://docs.microsoft.com/windows/uwp/style/segoe-ui-symbol-font
Or to use an IconElement instead of a Symbol see https://github.com/Microsoft/WindowsTemplateStudio/blob/master/docs/projectTypes/navigationpane.md
Edit String/en-US/Resources.resw: Add a menu item title for each page
TODO: Why isn't main page loading by default
-->
<winui:NavigationViewItem x:Uid="Shell_Main" Icon="Document" helpers:NavHelper.NavigateTo="views:MainPage" />
<winui:NavigationViewItem x:Uid="Shell_Test1" Icon="Document" helpers:NavHelper.NavigateTo="views:Test1Page" />
<winui:NavigationViewItem x:Uid="Shell_Test2" Icon="Document" helpers:NavHelper.NavigateTo="views:Test2Page" />
<winui:NavigationViewItem x:Uid="Shell_Test3" Icon="Document" helpers:NavHelper.NavigateTo="views:Test3Page" />
</winui:NavigationView.MenuItems>
<i:Interaction.Behaviors>
<behaviors:NavigationViewHeaderBehavior
DefaultHeader="{x:Bind ViewModel.Selected.Content, Mode=OneWay}">
<behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
<DataTemplate>
<!-- TODO: Style clean up-->
<Grid Margin="0, 24, 0, 6">
<TextBlock
Text="{Binding}"
FontWeight="Bold"
Style="{ThemeResource TitleTextBlockStyle}"
Margin="{StaticResource SmallLeftRightMargin}" />
</Grid>
</DataTemplate>
</behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
</behaviors:NavigationViewHeaderBehavior>
<ic:EventTriggerBehavior EventName="ItemInvoked">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.ItemInvokedCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<Grid>
<Frame x:Name="shellFrame" />
</Grid>
</winui:NavigationView>
</UserControl>

View File

@@ -0,0 +1,21 @@
using System;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
// TODO WTS: Change the icons and titles for all NavigationViewItems in ShellPage.xaml.
public sealed partial class ShellPage : UserControl
{
public ShellViewModel ViewModel { get; } = new ShellViewModel();
public ShellPage()
{
InitializeComponent();
DataContext = ViewModel;
ViewModel.Initialize(shellFrame, navigationView, KeyboardAccelerators);
}
}
}

View File

@@ -0,0 +1,18 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.Test1Page"
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"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,18 @@
using System;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class Test1Page : Page
{
public Test1ViewModel ViewModel { get; } = new Test1ViewModel();
public Test1Page()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,18 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.Test2Page"
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"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,18 @@
using System;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class Test2Page : Page
{
public Test2ViewModel ViewModel { get; } = new Test2ViewModel();
public Test2Page()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,18 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.Test3Page"
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"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,18 @@
using System;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class Test3Page : Page
{
public Test3ViewModel ViewModel { get; } = new Test3ViewModel();
public Test3Page()
{
InitializeComponent();
}
}
}