diff --git a/.filenesting.json b/.filenesting.json
new file mode 100644
index 0000000..7a09e65
--- /dev/null
+++ b/.filenesting.json
@@ -0,0 +1,14 @@
+{
+ "help": "https://go.microsoft.com/fwlink/?linkid=866610",
+ "dependentFileProviders": {
+ "add": {
+ "pathSegment": {
+ "add": {
+ ".*": [
+ ".cs"
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/CoreAppUWP/Controls/Setting/Setting.Properties.cs b/CoreAppUWP/Controls/Setting/Setting.Properties.cs
deleted file mode 100644
index 0adf19f..0000000
--- a/CoreAppUWP/Controls/Setting/Setting.Properties.cs
+++ /dev/null
@@ -1,281 +0,0 @@
-using Microsoft.UI.Xaml;
-using System;
-using System.ComponentModel;
-
-namespace CoreAppUWP.Controls
-{
- public partial class Setting
- {
- ///
- /// Gets or sets the content of a ContentControl.
- ///
- /// An object that contains the control's content. The default is .
- [Obsolete("Use Content instead of ActionContent.")]
- public object ActionContent => Content;
-
- #region Header
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty HeaderProperty =
- DependencyProperty.Register(
- nameof(Header),
- typeof(object),
- typeof(Setting),
- new PropertyMetadata(null, OnHeaderPropertyChanged));
-
- ///
- /// Gets or sets the Header.
- ///
- [Localizable(true)]
- public object Header
- {
- get => GetValue(HeaderProperty);
- set => SetValue(HeaderProperty, value);
- }
-
- private static void OnHeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue != e.OldValue)
- {
- ((Setting)d).OnHeaderChanged();
- }
- }
-
- #endregion
-
- #region Description
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty DescriptionProperty =
- DependencyProperty.Register(
- nameof(Description),
- typeof(object),
- typeof(Setting),
- new PropertyMetadata(null, OnDescriptionPropertyChanged));
-
- ///
- /// Gets or sets the description.
- ///
- [Localizable(true)]
- public object Description
- {
- get => GetValue(DescriptionProperty);
- set => SetValue(DescriptionProperty, value);
- }
-
- private static void OnDescriptionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue != e.OldValue)
- {
- ((Setting)d).OnDescriptionChanged();
- }
- }
-
- #endregion
-
- #region Icon
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty IconProperty =
- DependencyProperty.Register(
- nameof(Icon),
- typeof(object),
- typeof(Setting),
- new PropertyMetadata(null, OnIconPropertyChanged));
-
- ///
- /// Gets or sets the icon on the left.
- ///
- public object Icon
- {
- get => GetValue(IconProperty);
- set => SetValue(IconProperty, value);
- }
-
- private static void OnIconPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue != e.OldValue)
- {
- ((Setting)d).OnHeaderIconChanged();
- }
- }
-
- #endregion
-
- #region ActionIcon
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ActionIconProperty =
- DependencyProperty.Register(
- nameof(ActionIcon),
- typeof(object),
- typeof(Setting),
- new PropertyMetadata(null, OnActionIconPropertyChanged));
-
- ///
- /// Gets or sets the icon that is shown when IsClickEnabled is set to true.
- ///
- public object ActionIcon
- {
- get => GetValue(ActionIconProperty);
- set => SetValue(ActionIconProperty, value);
- }
-
- private static void OnActionIconPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue != e.OldValue)
- {
- ((Setting)d).OnButtonIconChanged();
- }
- }
-
- #endregion
-
- #region ActionIconToolTip
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ActionIconToolTipProperty =
- DependencyProperty.Register(
- nameof(ActionIconToolTip),
- typeof(string),
- typeof(Setting),
- new PropertyMetadata("More"));
-
- ///
- /// Gets or sets the tooltip of the ActionIcon.
- ///
- public string ActionIconToolTip
- {
- get => (string)GetValue(ActionIconToolTipProperty);
- set => SetValue(ActionIconToolTipProperty, value);
- }
-
- #endregion
-
- #region IsClickEnabled
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty IsClickEnabledProperty =
- DependencyProperty.Register(
- nameof(IsClickEnabled),
- typeof(bool),
- typeof(Setting),
- new PropertyMetadata(false, OnIsClickEnabledPropertyChanged));
-
- ///
- /// Gets or sets if the card can be clicked.
- ///
- public bool IsClickEnabled
- {
- get => (bool)GetValue(IsClickEnabledProperty);
- set => SetValue(IsClickEnabledProperty, value);
- }
-
- private static void OnIsClickEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.NewValue != e.OldValue)
- {
- ((Setting)d).OnIsClickEnabledChanged();
- }
- }
-
- #endregion
-
- #region ContentAlignment
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ContentAlignmentProperty =
- DependencyProperty.Register(
- nameof(ContentAlignment),
- typeof(ContentAlignment),
- typeof(Setting),
- new PropertyMetadata(ContentAlignment.Right));
-
- ///
- /// Gets or sets the alignment of the Content.
- ///
- public ContentAlignment ContentAlignment
- {
- get => (ContentAlignment)GetValue(ContentAlignmentProperty);
- set => SetValue(ContentAlignmentProperty, value);
- }
-
- #endregion
-
- #region WrapThreshold
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty WrapThresholdProperty =
- DependencyProperty.Register(
- nameof(WrapThreshold),
- typeof(double),
- typeof(Setting),
- new PropertyMetadata(476));
-
- ///
- /// Gets or sets the threshold of wrap.
- ///
- public double WrapThreshold
- {
- get => (double)GetValue(WrapThresholdProperty);
- set => SetValue(WrapThresholdProperty, value);
- }
-
- #endregion
-
- #region WrapNoIconThreshold
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty WrapNoIconThresholdProperty =
- DependencyProperty.Register(
- nameof(WrapNoIconThreshold),
- typeof(double),
- typeof(Setting),
- new PropertyMetadata(286));
-
- ///
- /// Gets or sets the threshold of wrap with no icon.
- ///
- public double WrapNoIconThreshold
- {
- get => (double)GetValue(WrapNoIconThresholdProperty);
- set => SetValue(WrapNoIconThresholdProperty, value);
- }
-
- #endregion
- }
-
- public enum ContentAlignment
- {
- ///
- /// The Content is aligned to the right. Default state.
- ///
- Right,
- ///
- /// The Content is left-aligned while the Header, HeaderIcon and Description are collapsed. This is commonly used for Content types such as CheckBoxes, RadioButtons and custom layouts.
- ///
- Left,
- ///
- /// The Content is vertically aligned.
- ///
- Vertical
- }
-}
diff --git a/CoreAppUWP/Controls/Setting/Setting.ThemeResources.xaml b/CoreAppUWP/Controls/Setting/Setting.ThemeResources.xaml
deleted file mode 100644
index 0a7b2e2..0000000
--- a/CoreAppUWP/Controls/Setting/Setting.ThemeResources.xaml
+++ /dev/null
@@ -1,890 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1
- 16,16,16,16
- 2,0,18,0
- 148
- 32
- 32
- 32
- 12
- 20
- 13
- 0
- 240
- 2,0,20,0
- 0,8,0,0
- 476
- 286
-
-
-
- 0,0,4,0
-
-
-
-
-
-
-
-
diff --git a/CoreAppUWP/Controls/Setting/Setting.cs b/CoreAppUWP/Controls/Setting/Setting.cs
deleted file mode 100644
index 612b34c..0000000
--- a/CoreAppUWP/Controls/Setting/Setting.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Automation;
-using Microsoft.UI.Xaml.Automation.Peers;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Controls.Primitives;
-using Microsoft.UI.Xaml.Input;
-
-// To learn more about WinUI, the WinUI project structure,
-// and more about our project templates, see: http://aka.ms/winui-project-info.
-
-namespace CoreAppUWP.Controls
-{
- ///
- /// This is the base control to create consistent settings experiences, inline with the Windows 11 design language.
- /// A Setting can also be hosted within a SettingExpander.
- ///
- public partial class Setting : ButtonBase
- {
- internal const string NormalState = "Normal";
- internal const string PointerOverState = "PointerOver";
- internal const string PressedState = "Pressed";
- internal const string DisabledState = "Disabled";
-
- internal const string ContentPresenter = "PART_ContentPresenter";
- internal const string HeaderIconPresenterHolder = "PART_HeaderIconPresenterHolder";
-
- ///
- /// Creates a new instance of the class.
- ///
- public Setting()
- {
- DefaultStyleKey = typeof(Setting);
- }
-
- ///
- protected override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- IsEnabledChanged -= OnIsEnabledChanged;
- OnButtonIconChanged();
- OnHeaderChanged();
- OnHeaderIconChanged();
- OnDescriptionChanged();
- OnContentChanged();
- OnIsClickEnabledChanged();
- _ = VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
- RegisterAutomation();
- IsEnabledChanged += OnIsEnabledChanged;
- }
-
- private void RegisterAutomation()
- {
- if (Header is string headerString && headerString != string.Empty)
- {
- AutomationProperties.SetName(this, headerString);
- // We don't want to override an AutomationProperties.Name that is manually set, or if the Content basetype is of type ButtonBase (the ButtonBase.Content will be used then)
- if (Content is UIElement element
- && string.IsNullOrEmpty(AutomationProperties.GetName(element))
- && element is not ButtonBase or TextBlock)
- {
- AutomationProperties.SetName(element, headerString);
- }
- }
- }
-
- private void EnableButtonInteraction()
- {
- DisableButtonInteraction();
-
- PointerEntered += Control_PointerEntered;
- PointerExited += Control_PointerExited;
- PointerCaptureLost += Control_PointerCaptureLost;
- PointerCanceled += Control_PointerCanceled;
- PreviewKeyDown += Control_PreviewKeyDown;
- PreviewKeyUp += Control_PreviewKeyUp;
- }
-
- private void DisableButtonInteraction()
- {
- PointerEntered -= Control_PointerEntered;
- PointerExited -= Control_PointerExited;
- PointerCaptureLost -= Control_PointerCaptureLost;
- PointerCanceled -= Control_PointerCanceled;
- PreviewKeyDown -= Control_PreviewKeyDown;
- PreviewKeyUp -= Control_PreviewKeyUp;
- }
-
- private void Control_PreviewKeyUp(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key is Windows.System.VirtualKey.Enter or Windows.System.VirtualKey.Space or Windows.System.VirtualKey.GamepadA)
- {
- _ = VisualStateManager.GoToState(this, NormalState, true);
- }
- }
-
- private void Control_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key is Windows.System.VirtualKey.Enter or Windows.System.VirtualKey.Space or Windows.System.VirtualKey.GamepadA)
- {
- _ = VisualStateManager.GoToState(this, PressedState, true);
- }
- }
-
- public void Control_PointerEntered(object sender, PointerRoutedEventArgs e)
- {
- base.OnPointerEntered(e);
- _ = VisualStateManager.GoToState(this, PointerOverState, true);
- }
-
- public void Control_PointerExited(object sender, PointerRoutedEventArgs e)
- {
- base.OnPointerExited(e);
- _ = VisualStateManager.GoToState(this, NormalState, true);
- }
-
- private void Control_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
- {
- base.OnPointerCaptureLost(e);
- _ = VisualStateManager.GoToState(this, NormalState, true);
- }
-
- private void Control_PointerCanceled(object sender, PointerRoutedEventArgs e)
- {
- base.OnPointerCanceled(e);
- _ = VisualStateManager.GoToState(this, NormalState, true);
- }
-
- protected override void OnPointerPressed(PointerRoutedEventArgs e)
- {
- // e.Handled = true;
- if (IsClickEnabled)
- {
- base.OnPointerPressed(e);
- _ = VisualStateManager.GoToState(this, PressedState, true);
- }
- }
-
- protected override void OnPointerReleased(PointerRoutedEventArgs e)
- {
- if (IsClickEnabled)
- {
- base.OnPointerReleased(e);
- _ = VisualStateManager.GoToState(this, NormalState, true);
- }
- }
-
- protected override void OnContentChanged(object oldContent, object newContent)
- {
- base.OnContentChanged(oldContent, newContent);
- OnContentChanged();
- }
-
- ///
- /// Creates AutomationPeer
- ///
- /// An automation peer for .
- protected override AutomationPeer OnCreateAutomationPeer()
- {
- return new SettingAutomationPeer(this);
- }
-
- private void OnIsClickEnabledChanged()
- {
- OnButtonIconChanged();
- if (IsClickEnabled)
- {
- EnableButtonInteraction();
- }
- else
- {
- DisableButtonInteraction();
- }
- }
-
- private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- _ = VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
- }
-
-
- public void OnButtonIconChanged()
- {
- _ = VisualStateManager.GoToState(this, IsClickEnabled && ActionIcon != null ? "ActionIconVisible" : "ActionIconCollapsed", false);
- }
-
- public void OnHeaderIconChanged()
- {
- if (GetTemplateChild(HeaderIconPresenterHolder) is FrameworkElement headerIconPresenter)
- {
- headerIconPresenter.Visibility = Icon != null
- ? Visibility.Visible
- : Visibility.Collapsed;
- }
- }
-
- public void OnContentChanged()
- {
- if (GetTemplateChild(ContentPresenter) is FrameworkElement contentPresenter)
- {
- contentPresenter.Visibility = Content != null
- ? Visibility.Visible
- : Visibility.Collapsed;
- }
- }
-
- public void OnDescriptionChanged()
- {
- _ = VisualStateManager.GoToState(this, Description == null ? "DescriptionCollapsed" : "DescriptionVisible", false);
- }
-
- public void OnHeaderChanged()
- {
- _ = VisualStateManager.GoToState(this, Header == null ? "HeaderCollapsed" : "HeaderVisible", false);
- }
- }
-}
diff --git a/CoreAppUWP/Controls/Setting/Setting.xaml b/CoreAppUWP/Controls/Setting/Setting.xaml
deleted file mode 100644
index 218f619..0000000
--- a/CoreAppUWP/Controls/Setting/Setting.xaml
+++ /dev/null
@@ -1,319 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CoreAppUWP/Controls/Setting/SettingAutomationPeer.cs b/CoreAppUWP/Controls/Setting/SettingAutomationPeer.cs
deleted file mode 100644
index 444418d..0000000
--- a/CoreAppUWP/Controls/Setting/SettingAutomationPeer.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Microsoft.UI.Xaml.Automation.Peers;
-
-namespace CoreAppUWP.Controls
-{
- ///
- /// AutomationPeer for SettingsCard
- ///
- /// Setting
- public class SettingAutomationPeer(Setting owner) : ButtonBaseAutomationPeer(owner)
- {
- ///
- /// Gets the control type for the element that is associated with the UI Automation peer.
- ///
- /// The control type.
- protected override AutomationControlType GetAutomationControlTypeCore()
- {
- return AutomationControlType.Group;
- }
-
- ///
- /// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
- /// differentiates the control represented by this AutomationPeer.
- ///
- /// The string that contains the name.
- protected override string GetClassNameCore()
- {
- string classNameCore = Owner.GetType().Name;
-#if DEBUG_AUTOMATION
- System.Diagnostics.Debug.WriteLine("SettingsCardAutomationPeer.GetClassNameCore returns " + classNameCore);
-#endif
- return classNameCore;
- }
- }
-}
diff --git a/CoreAppUWP/Controls/SettingExpander/SettingExpander.Properties.cs b/CoreAppUWP/Controls/SettingExpander/SettingExpander.Properties.cs
deleted file mode 100644
index 71f77eb..0000000
--- a/CoreAppUWP/Controls/SettingExpander/SettingExpander.Properties.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-using Microsoft.UI.Xaml;
-using System.ComponentModel;
-
-namespace CoreAppUWP.Controls
-{
- public partial class SettingExpander
- {
- #region Header
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty HeaderProperty =
- DependencyProperty.Register(
- nameof(Header),
- typeof(object),
- typeof(SettingExpander),
- new PropertyMetadata(null));
-
- ///
- /// Gets or sets the Header.
- ///
- [Localizable(true)]
- public object Header
- {
- get => GetValue(HeaderProperty);
- set => SetValue(HeaderProperty, value);
- }
-
- #endregion
-
- #region Description
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty DescriptionProperty =
- DependencyProperty.Register(
- nameof(Description),
- typeof(object),
- typeof(SettingExpander),
- new PropertyMetadata(null));
-
- ///
- /// Gets or sets the Description.
- ///
- [Localizable(true)]
- public object Description
- {
- get => GetValue(DescriptionProperty);
- set => SetValue(DescriptionProperty, value);
- }
-
- #endregion
-
- #region ActionContent
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ActionContentProperty =
- DependencyProperty.Register(
- nameof(ActionContent),
- typeof(object),
- typeof(SettingExpander),
- new PropertyMetadata(null));
-
- ///
- /// Gets or sets the content of a Setting.
- ///
- /// An object that contains the setting's content. The default is .
- public object ActionContent
- {
- get => GetValue(ActionContentProperty);
- set => SetValue(ActionContentProperty, value);
- }
-
- #endregion
-
- #region Icon
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty IconProperty =
- DependencyProperty.Register(
- nameof(Icon),
- typeof(object),
- typeof(SettingExpander),
- new PropertyMetadata(default(string)));
-
- ///
- /// Gets or sets the icon on the left.
- ///
- public object Icon
- {
- get => GetValue(IconProperty);
- set => SetValue(IconProperty, value);
- }
-
- #endregion
-
- #region ContentAlignment
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ContentAlignmentProperty =
- DependencyProperty.Register(
- nameof(ContentAlignment),
- typeof(ContentAlignment),
- typeof(SettingExpander),
- new PropertyMetadata(ContentAlignment.Right));
-
- ///
- /// Gets or sets the alignment of the Content
- ///
- public ContentAlignment ContentAlignment
- {
- get => (ContentAlignment)GetValue(ContentAlignmentProperty);
- set => SetValue(ContentAlignmentProperty, value);
- }
-
- #endregion
-
- #region ItemsHeader
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ItemsHeaderProperty =
- DependencyProperty.Register(
- nameof(ItemsHeader),
- typeof(UIElement),
- typeof(SettingExpander),
- new PropertyMetadata(null));
-
- ///
- /// Gets or sets the ItemsFooter.
- ///
- public UIElement ItemsHeader
- {
- get => (UIElement)GetValue(ItemsHeaderProperty);
- set => SetValue(ItemsHeaderProperty, value);
- }
-
- #endregion
-
- #region ItemsFooter
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ItemsFooterProperty =
- DependencyProperty.Register(
- nameof(ItemsFooter),
- typeof(UIElement),
- typeof(SettingExpander),
- new PropertyMetadata(null));
-
- ///
- /// Gets or sets the ItemsFooter.
- ///
- public UIElement ItemsFooter
- {
- get => (UIElement)GetValue(ItemsFooterProperty);
- set => SetValue(ItemsFooterProperty, value);
- }
-
- #endregion
-
- #region IsExpanded
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty IsExpandedProperty =
- DependencyProperty.Register(
- nameof(IsExpanded),
- typeof(bool),
- typeof(SettingExpander),
- new PropertyMetadata(false));
-
- ///
- /// Gets or sets the IsExpanded state.
- ///
- public bool IsExpanded
- {
- get => (bool)GetValue(IsExpandedProperty);
- set => SetValue(IsExpandedProperty, value);
- }
-
- #endregion
- }
-}
diff --git a/CoreAppUWP/Controls/SettingExpander/SettingExpander.ThemeResources.xaml b/CoreAppUWP/Controls/SettingExpander/SettingExpander.ThemeResources.xaml
deleted file mode 100644
index 4853eed..0000000
--- a/CoreAppUWP/Controls/SettingExpander/SettingExpander.ThemeResources.xaml
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
- 0
- 8,0
-
- Show all settings
- 0,16,0,16
- 40,16,0,16
- 58,8,44,8
- 0,1,0,0
- 58,8,16,8
-
- 410
- 220
-
- 474
- 284
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CoreAppUWP/Controls/SettingExpander/SettingExpander.cs b/CoreAppUWP/Controls/SettingExpander/SettingExpander.cs
deleted file mode 100644
index c49123e..0000000
--- a/CoreAppUWP/Controls/SettingExpander/SettingExpander.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Microsoft.UI.Xaml.Automation;
-using Microsoft.UI.Xaml.Automation.Peers;
-using Microsoft.UI.Xaml.Controls;
-
-// To learn more about WinUI, the WinUI project structure,
-// and more about our project templates, see: http://aka.ms/winui-project-info.
-
-namespace CoreAppUWP.Controls
-{
- ///
- /// The SettingExpander is a collapsable control to host multiple SettingsCards.
- ///
- public partial class SettingExpander : ItemsControl
- {
- ///
- /// Creates a new instance of the class.
- ///
- public SettingExpander()
- {
- DefaultStyleKey = typeof(SettingExpander);
- }
-
- ///
- protected override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- RegisterAutomation();
- }
-
- private void RegisterAutomation()
- {
- if (Header is string headerString && headerString != string.Empty)
- {
- if (!string.IsNullOrEmpty(headerString) && string.IsNullOrEmpty(AutomationProperties.GetName(this)))
- {
- AutomationProperties.SetName(this, headerString);
- }
- }
- }
-
- ///
- /// Creates AutomationPeer
- ///
- /// An automation peer for .
- protected override AutomationPeer OnCreateAutomationPeer()
- {
- return new SettingExpanderAutomationPeer(this);
- }
- }
-}
diff --git a/CoreAppUWP/Controls/SettingExpander/SettingExpander.xaml b/CoreAppUWP/Controls/SettingExpander/SettingExpander.xaml
deleted file mode 100644
index 0b60c9d..0000000
--- a/CoreAppUWP/Controls/SettingExpander/SettingExpander.xaml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/CoreAppUWP/Controls/SettingExpander/SettingExpanderAutomationPeer.cs b/CoreAppUWP/Controls/SettingExpander/SettingExpanderAutomationPeer.cs
deleted file mode 100644
index ce47426..0000000
--- a/CoreAppUWP/Controls/SettingExpander/SettingExpanderAutomationPeer.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Microsoft.UI.Xaml.Automation.Peers;
-
-namespace CoreAppUWP.Controls
-{
- ///
- /// AutomationPeer for SettingExpander
- ///
- public class SettingExpanderAutomationPeer : ItemsControlAutomationPeer
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// SettingExpander
- public SettingExpanderAutomationPeer(SettingExpander owner) : base(owner)
- {
- }
-
- ///
- /// Gets the control type for the element that is associated with the UI Automation peer.
- ///
- /// The control type.
- protected override AutomationControlType GetAutomationControlTypeCore()
- {
- return AutomationControlType.Button;
- }
-
- ///
- /// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
- /// differentiates the control represented by this AutomationPeer.
- ///
- /// The string that contains the name.
- protected override string GetClassNameCore()
- {
- string classNameCore = Owner.GetType().Name;
-#if DEBUG_AUTOMATION
- System.Diagnostics.Debug.WriteLine("SettingsCardAutomationPeer.GetClassNameCore returns " + classNameCore);
-#endif
- return classNameCore;
- }
- }
-}
diff --git a/CoreAppUWP/Controls/SettingsExpanderItemStyleSelector.cs b/CoreAppUWP/Controls/SettingsExpanderItemStyleSelector.cs
new file mode 100644
index 0000000..e7c2d74
--- /dev/null
+++ b/CoreAppUWP/Controls/SettingsExpanderItemStyleSelector.cs
@@ -0,0 +1,24 @@
+using CommunityToolkit.WinUI.Controls;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace CoreAppUWP.Controls
+{
+ public class SettingsExpanderItemStyleSelector : CommunityToolkit.WinUI.Controls.SettingsExpanderItemStyleSelector
+ {
+ public Style GridStyle { get; set; }
+ public Style BorderStyle { get; set; }
+ public Style StackPanelStyle { get; set; }
+
+ protected override Style SelectStyleCore(object item, DependencyObject container) =>
+ container switch
+ {
+ SettingsCard card => card.IsClickEnabled ? ClickableStyle : DefaultStyle,
+ Grid => GridStyle,
+ Border => BorderStyle,
+ StackPanel => StackPanelStyle,
+ FrameworkElement element => element.Style,
+ _ => null
+ };
+ }
+}
diff --git a/CoreAppUWP/CoreAppUWP.csproj b/CoreAppUWP/CoreAppUWP.csproj
index 5057f90..e89e406 100644
--- a/CoreAppUWP/CoreAppUWP.csproj
+++ b/CoreAppUWP/CoreAppUWP.csproj
@@ -19,19 +19,18 @@
-
-
-
-
+
+
+
+
-
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/CoreAppUWP/Helpers/ApplicationDataStorageHelper.CacheFolder.cs b/CoreAppUWP/Helpers/ApplicationDataStorageHelper.CacheFolder.cs
new file mode 100644
index 0000000..ca3b260
--- /dev/null
+++ b/CoreAppUWP/Helpers/ApplicationDataStorageHelper.CacheFolder.cs
@@ -0,0 +1,87 @@
+// 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 CommunityToolkit.Common.Helpers;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Windows.Storage;
+
+namespace CoreAppUWP.Helpers
+{
+ ///
+ /// An extension of ApplicationDataStorageHelper with additional features for interop with the LocalCacheFolder.
+ ///
+ public partial class ApplicationDataStorageHelper
+ {
+ ///
+ /// Gets the local cache folder.
+ ///
+ public StorageFolder CacheFolder => AppData.LocalCacheFolder;
+
+ ///
+ /// Retrieves an object from a file in the LocalCacheFolder.
+ ///
+ /// Type of object retrieved.
+ /// Path to the file that contains the object.
+ /// Default value of the object.
+ /// Waiting task until completion with the object in the file.
+ public Task ReadCacheFileAsync(string filePath, T @default = default)
+ {
+ return ReadFileAsync(CacheFolder, filePath, @default);
+ }
+
+ ///
+ /// Retrieves the listings for a folder and the item types in the LocalCacheFolder.
+ ///
+ /// The path to the target folder.
+ /// A list of file types and names in the target folder.
+ public Task> ReadCacheFolderAsync(string folderPath)
+ {
+ return ReadFolderAsync(CacheFolder, folderPath);
+ }
+
+ ///
+ /// Saves an object inside a file in the LocalCacheFolder.
+ ///
+ /// Type of object saved.
+ /// Path to the file that will contain the object.
+ /// Object to save.
+ /// Waiting task until completion.
+ public Task CreateCacheFileAsync(string filePath, T value)
+ {
+ return CreateFileAsync(CacheFolder, filePath, value);
+ }
+
+ ///
+ /// Ensure a folder exists at the folder path specified in the LocalCacheFolder.
+ ///
+ /// The path and name of the target folder.
+ /// Waiting task until completion.
+ public Task CreateCacheFolderAsync(string folderPath)
+ {
+ return CreateFolderAsync(CacheFolder, folderPath);
+ }
+
+ ///
+ /// Deletes a file or folder item in the LocalCacheFolder.
+ ///
+ /// The path to the item for deletion.
+ /// Waiting task until completion.
+ public Task TryDeleteCacheItemAsync(string itemPath)
+ {
+ return TryDeleteItemAsync(CacheFolder, itemPath);
+ }
+
+ ///
+ /// Rename an item in the LocalCacheFolder.
+ ///
+ /// The path to the target item.
+ /// The new nam for the target item.
+ /// Waiting task until completion.
+ public Task TryRenameCacheItemAsync(string itemPath, string newName)
+ {
+ return TryRenameItemAsync(CacheFolder, itemPath, newName);
+ }
+ }
+}
diff --git a/CoreAppUWP/Helpers/ApplicationDataStorageHelper.cs b/CoreAppUWP/Helpers/ApplicationDataStorageHelper.cs
new file mode 100644
index 0000000..ce631eb
--- /dev/null
+++ b/CoreAppUWP/Helpers/ApplicationDataStorageHelper.cs
@@ -0,0 +1,333 @@
+// 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 CommunityToolkit.Common.Helpers;
+using CommunityToolkit.Helpers;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Storage;
+using Windows.System;
+
+namespace CoreAppUWP.Helpers
+{
+ ///
+ /// Storage helper for files and folders living in Windows.Storage.ApplicationData storage endpoints.
+ ///
+ public partial class ApplicationDataStorageHelper : IFileStorageHelper, ISettingsStorageHelper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The data store to interact with.
+ /// Serializer for converting stored values. Defaults to .
+ public ApplicationDataStorageHelper(ApplicationData appData, IObjectSerializer objectSerializer = null)
+ {
+ AppData = appData ?? throw new ArgumentNullException(nameof(appData));
+ Serializer = objectSerializer ?? new SystemSerializer();
+ }
+
+ ///
+ /// Gets the settings container.
+ ///
+ public ApplicationDataContainer Settings => AppData.LocalSettings;
+
+ ///
+ /// Gets the storage folder.
+ ///
+ public StorageFolder Folder => AppData.LocalFolder;
+
+ ///
+ /// Gets the storage host.
+ ///
+ protected ApplicationData AppData { get; }
+
+ ///
+ /// Gets the serializer for converting stored values.
+ ///
+ protected IObjectSerializer Serializer { get; }
+
+ ///
+ /// Get a new instance using ApplicationData.Current and the provided serializer.
+ ///
+ /// Serializer for converting stored values. Defaults to .
+ /// A new instance of ApplicationDataStorageHelper.
+ public static ApplicationDataStorageHelper GetCurrent(IObjectSerializer objectSerializer = null)
+ {
+ ApplicationData appData = ApplicationData.Current;
+ return new ApplicationDataStorageHelper(appData, objectSerializer);
+ }
+
+ ///
+ /// Get a new instance using the ApplicationData for the provided user and serializer.
+ ///
+ /// App data user owner.
+ /// Serializer for converting stored values. Defaults to .
+ /// A new instance of ApplicationDataStorageHelper.
+ public static async Task GetForUserAsync(User user, IObjectSerializer objectSerializer = null)
+ {
+ ApplicationData appData = await ApplicationData.GetForUserAsync(user);
+ return new ApplicationDataStorageHelper(appData, objectSerializer);
+ }
+
+ ///
+ /// Determines whether a setting already exists.
+ ///
+ /// Key of the setting (that contains object).
+ /// True if a value exists.
+ public bool KeyExists(string key)
+ {
+ return Settings.Values.ContainsKey(key);
+ }
+
+ ///
+ /// Retrieves a single item by its key.
+ ///
+ /// Type of object retrieved.
+ /// Key of the object.
+ /// Default value of the object.
+ /// The TValue object.
+ public T Read(string key, T @default = default)
+ {
+ return Settings.Values.TryGetValue(key, out object valueObj) && valueObj is string valueString
+ ? Serializer.Deserialize(valueString)
+ : @default;
+ }
+
+ ///
+ public bool TryRead(string key, out T value)
+ {
+ if (Settings.Values.TryGetValue(key, out object valueObj) && valueObj is string valueString)
+ {
+ value = Serializer.Deserialize(valueString);
+ return true;
+ }
+
+ value = default;
+ return false;
+ }
+
+ ///
+ public void Save(string key, T value)
+ {
+ Settings.Values[key] = Serializer.Serialize(value);
+ }
+
+ ///
+ public bool TryDelete(string key)
+ {
+ return Settings.Values.Remove(key);
+ }
+
+ ///
+ public void Clear()
+ {
+ Settings.Values.Clear();
+ }
+
+ ///
+ /// Determines whether a setting already exists in composite.
+ ///
+ /// Key of the composite (that contains settings).
+ /// Key of the setting (that contains object).
+ /// True if a value exists.
+ public bool KeyExists(string compositeKey, string key)
+ {
+ return TryRead(compositeKey, out ApplicationDataCompositeValue composite) && composite != null && composite.ContainsKey(key);
+ }
+
+ ///
+ /// Attempts to retrieve a single item by its key in composite.
+ ///
+ /// Type of object retrieved.
+ /// Key of the composite (that contains settings).
+ /// Key of the object.
+ /// The value of the object retrieved.
+ /// The T object.
+ public bool TryRead(string compositeKey, string key, out T value)
+ {
+ if (TryRead(compositeKey, out ApplicationDataCompositeValue composite) && composite != null)
+ {
+ string compositeValue = (string)composite[key];
+ if (compositeValue != null)
+ {
+ value = Serializer.Deserialize(compositeValue);
+ return true;
+ }
+ }
+
+ value = default;
+ return false;
+ }
+
+ ///
+ /// Retrieves a single item by its key in composite.
+ ///
+ /// Type of object retrieved.
+ /// Key of the composite (that contains settings).
+ /// Key of the object.
+ /// Default value of the object.
+ /// The T object.
+ public T Read(string compositeKey, string key, T @default = default)
+ {
+ if (TryRead(compositeKey, out ApplicationDataCompositeValue composite) && composite != null)
+ {
+ if (composite.TryGetValue(key, out object valueObj) && valueObj is string value)
+ {
+ return Serializer.Deserialize(value);
+ }
+ }
+
+ return @default;
+ }
+
+ ///
+ /// Saves a group of items by its key in a composite.
+ /// This method should be considered for objects that do not exceed 8k bytes during the lifetime of the application
+ /// and for groups of settings which need to be treated in an atomic way.
+ ///
+ /// Type of object saved.
+ /// Key of the composite (that contains settings).
+ /// Objects to save.
+ public void Save(string compositeKey, IDictionary values)
+ {
+ if (TryRead(compositeKey, out ApplicationDataCompositeValue composite) && composite != null)
+ {
+ foreach (KeyValuePair setting in values)
+ {
+ if (composite.ContainsKey(setting.Key))
+ {
+ composite[setting.Key] = Serializer.Serialize(setting.Value);
+ }
+ else
+ {
+ composite.Add(setting.Key, Serializer.Serialize(setting.Value));
+ }
+ }
+ }
+ else
+ {
+ composite = [];
+ foreach (KeyValuePair setting in values)
+ {
+ composite.Add(setting.Key, Serializer.Serialize(setting.Value));
+ }
+
+ Settings.Values[compositeKey] = composite;
+ }
+ }
+
+ ///
+ /// Deletes a single item by its key in composite.
+ ///
+ /// Key of the composite (that contains settings).
+ /// Key of the object.
+ /// A boolean indicator of success.
+ public bool TryDelete(string compositeKey, string key)
+ {
+ return TryRead(compositeKey, out ApplicationDataCompositeValue composite) && composite != null && composite.Remove(key);
+ }
+
+ ///
+ public Task ReadFileAsync(string filePath, T @default = default)
+ {
+ return ReadFileAsync(Folder, filePath, @default);
+ }
+
+ ///
+ public Task> ReadFolderAsync(string folderPath)
+ {
+ return ReadFolderAsync(Folder, folderPath);
+ }
+
+ ///
+ public Task CreateFileAsync(string filePath, T value)
+ {
+ return CreateFileAsync(Folder, filePath, value);
+ }
+
+ ///
+ public Task CreateFolderAsync(string folderPath)
+ {
+ return CreateFolderAsync(Folder, folderPath);
+ }
+
+ ///
+ public Task TryDeleteItemAsync(string itemPath)
+ {
+ return TryDeleteItemAsync(Folder, itemPath);
+ }
+
+ ///
+ public Task TryRenameItemAsync(string itemPath, string newName)
+ {
+ return TryRenameItemAsync(Folder, itemPath, newName);
+ }
+
+ private async Task ReadFileAsync(StorageFolder folder, string filePath, T @default = default)
+ {
+ string value = await StorageFileHelper.ReadTextFromFileAsync(folder, NormalizePath(filePath));
+ return (value != null) ? Serializer.Deserialize(value) : @default;
+ }
+
+ private async Task> ReadFolderAsync(StorageFolder folder, string folderPath)
+ {
+ StorageFolder targetFolder = await folder.GetFolderAsync(NormalizePath(folderPath));
+ IReadOnlyList items = await targetFolder.GetItemsAsync();
+
+ return items.Select((item) =>
+ {
+ DirectoryItemType itemType = item.IsOfType(StorageItemTypes.File) ? DirectoryItemType.File
+ : item.IsOfType(StorageItemTypes.Folder) ? DirectoryItemType.Folder
+ : DirectoryItemType.None;
+ return (itemType, item.Name);
+ });
+ }
+
+ private async Task CreateFileAsync(StorageFolder folder, string filePath, T value)
+ {
+ return await StorageFileHelper.WriteTextToFileAsync(folder, Serializer.Serialize(value)?.ToString(), NormalizePath(filePath), CreationCollisionOption.ReplaceExisting);
+ }
+
+ private async Task CreateFolderAsync(StorageFolder folder, string folderPath)
+ {
+ await folder.CreateFolderAsync(NormalizePath(folderPath), CreationCollisionOption.OpenIfExists);
+ }
+
+ private async Task TryDeleteItemAsync(StorageFolder folder, string itemPath)
+ {
+ try
+ {
+ IStorageItem item = await folder.GetItemAsync(NormalizePath(itemPath));
+ await item.DeleteAsync();
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private async Task TryRenameItemAsync(StorageFolder folder, string itemPath, string newName)
+ {
+ try
+ {
+ IStorageItem item = await folder.GetItemAsync(NormalizePath(itemPath));
+ await item.RenameAsync(newName, NameCollisionOption.FailIfExists);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private string NormalizePath(string path)
+ {
+ return Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path));
+ }
+ }
+}
diff --git a/CoreAppUWP/Helpers/BackdropHelper.cs b/CoreAppUWP/Helpers/BackdropHelper.cs
index e0a8d64..eb627e4 100644
--- a/CoreAppUWP/Helpers/BackdropHelper.cs
+++ b/CoreAppUWP/Helpers/BackdropHelper.cs
@@ -6,6 +6,7 @@
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
using Windows.UI;
using WinRT; // required to support Window.As()
@@ -346,4 +347,59 @@ public static void RemoveBackdropTypeChanged(this DesktopWindow window, Action> ActiveWindows { get; } = [];
public static Dictionary> ActiveDesktopWindows { get; } = [];
}
+
+ public partial class WindowsSystemDispatcherQueueHelper
+ {
+ ///
+ /// Specifies the threading and apartment type for a new DispatcherQueueController.
+ ///
+ /// Introduced in Windows 10, version 1709.
+ [StructLayout(LayoutKind.Sequential)]
+ private struct DispatcherQueueOptions
+ {
+ ///
+ /// Size of this structure.
+ ///
+ public int DWSize;
+
+ ///
+ /// Thread affinity for the created DispatcherQueueController.
+ ///
+ public int ThreadType;
+
+ ///
+ /// Specifies whether to initialize COM apartment on the new thread as an application single-threaded apartment (ASTA)
+ /// or single-threaded apartment (STA). This field is only relevant if threadType is DQTYPE_THREAD_DEDICATED.
+ /// Use DQTAT_COM_NONE when DispatcherQueueOptions.threadType is DQTYPE_THREAD_CURRENT.
+ ///
+ public int ApartmentType;
+ }
+
+ [LibraryImport("CoreMessaging.dll")]
+ private static unsafe partial int CreateDispatcherQueueController(DispatcherQueueOptions options, out nint instance);
+
+ private nint m_dispatcherQueueController = 0;
+ public void EnsureWindowsSystemDispatcherQueueController()
+ {
+ if (Windows.System.DispatcherQueue.GetForCurrentThread() != null)
+ {
+ // one already exists, so we'll just use it.
+ return;
+ }
+
+ if (m_dispatcherQueueController == 0)
+ {
+ DispatcherQueueOptions options;
+ options.DWSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
+ options.ThreadType = 2; // DQTYPE_THREAD_CURRENT
+ options.ApartmentType = 2; // DQTAT_COM_STA
+
+ unsafe
+ {
+ _ = CreateDispatcherQueueController(options, out nint dispatcherQueueController);
+ m_dispatcherQueueController = dispatcherQueueController;
+ }
+ }
+ }
+ }
}
diff --git a/CoreAppUWP/Helpers/Controls/SettingsCardHelper.cs b/CoreAppUWP/Helpers/Controls/SettingsCardHelper.cs
new file mode 100644
index 0000000..ce974c8
--- /dev/null
+++ b/CoreAppUWP/Helpers/Controls/SettingsCardHelper.cs
@@ -0,0 +1,69 @@
+using CommunityToolkit.WinUI;
+using CommunityToolkit.WinUI.Controls;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace CoreAppUWP.Helpers
+{
+ public static class SettingsCardHelper
+ {
+ #region HeaderIcon
+
+ ///
+ /// Identifies the HeaderIcon dependency property.
+ ///
+ public static readonly DependencyProperty HeaderIconProperty =
+ DependencyProperty.RegisterAttached(
+ "HeaderIcon",
+ typeof(object),
+ typeof(SettingsExpanderHelper),
+ new PropertyMetadata(null, OnHeaderIconChanged));
+
+ ///
+ /// Gets the HeaderIcon.
+ ///
+ /// The element from which to read the property value.
+ /// The HeaderIcon.
+ public static object GetHeaderIcon(SettingsCard control)
+ {
+ return control.GetValue(HeaderIconProperty);
+ }
+
+ ///
+ /// Sets the HeaderIcon.
+ ///
+ /// The element on which to set the attached property.
+ /// The property value to set.
+ public static void SetHeaderIcon(SettingsCard control, object value)
+ {
+ control.SetValue(HeaderIconProperty, value);
+ }
+
+ private static void OnHeaderIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not SettingsCard element) { return; }
+ if (element.IsLoaded)
+ {
+ OnElementLoaded(element, null);
+ }
+ else
+ {
+ element.Loaded -= OnElementLoaded;
+ element.Loaded += OnElementLoaded;
+ }
+ }
+
+ private static void OnElementLoaded(object sender, RoutedEventArgs e)
+ {
+ if (sender is not SettingsCard element) { return; }
+ object content = GetHeaderIcon(element);
+ element.HeaderIcon = content == null ? null : new SymbolIcon();
+ if (element.FindDescendant("PART_HeaderIconPresenter") is ContentPresenter presenter)
+ {
+ presenter.Content = content;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAppUWP/Helpers/Controls/SettingsExpanderHelper.cs b/CoreAppUWP/Helpers/Controls/SettingsExpanderHelper.cs
new file mode 100644
index 0000000..27276f7
--- /dev/null
+++ b/CoreAppUWP/Helpers/Controls/SettingsExpanderHelper.cs
@@ -0,0 +1,67 @@
+using CommunityToolkit.WinUI;
+using CommunityToolkit.WinUI.Controls;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace CoreAppUWP.Helpers
+{
+ public static class SettingsExpanderHelper
+ {
+ #region HeaderIcon
+
+ ///
+ /// Identifies the HeaderIcon dependency property.
+ ///
+ public static readonly DependencyProperty HeaderIconProperty =
+ DependencyProperty.RegisterAttached(
+ "HeaderIcon",
+ typeof(object),
+ typeof(SettingsExpanderHelper),
+ new PropertyMetadata(null, OnHeaderIconChanged));
+
+ ///
+ /// Gets the HeaderIcon.
+ ///
+ /// The element from which to read the property value.
+ /// The HeaderIcon.
+ public static object GetHeaderIcon(SettingsExpander control)
+ {
+ return control.GetValue(HeaderIconProperty);
+ }
+
+ ///
+ /// Sets the HeaderIcon.
+ ///
+ /// The element on which to set the attached property.
+ /// The property value to set.
+ public static void SetHeaderIcon(SettingsExpander control, object value)
+ {
+ control.SetValue(HeaderIconProperty, value);
+ }
+
+ private static void OnHeaderIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not FrameworkElement element) { return; }
+ if (element.IsLoaded)
+ {
+ OnElementLoaded(element, null);
+ }
+ else
+ {
+ element.Loaded -= OnElementLoaded;
+ element.Loaded += OnElementLoaded;
+ }
+ }
+
+ private static void OnElementLoaded(object sender, RoutedEventArgs e)
+ {
+ if (sender is not SettingsExpander element) { return; }
+ if (element.FindDescendant() is Expander expander && expander.Header is SettingsCard settings)
+ {
+ SettingsCardHelper.SetHeaderIcon(settings, GetHeaderIcon(element));
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/CoreAppUWP/Helpers/DispatcherQueueHelper.cs b/CoreAppUWP/Helpers/DispatcherQueueHelper.cs
deleted file mode 100644
index 6328e71..0000000
--- a/CoreAppUWP/Helpers/DispatcherQueueHelper.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System.Runtime.InteropServices; // For DllImport
-using Windows.System;
-
-namespace CoreAppUWP.Helpers
-{
- public partial class WindowsSystemDispatcherQueueHelper
- {
- ///
- /// Specifies the threading and apartment type for a new DispatcherQueueController.
- ///
- /// Introduced in Windows 10, version 1709.
- [StructLayout(LayoutKind.Sequential)]
- private struct DispatcherQueueOptions
- {
- ///
- /// Size of this structure.
- ///
- public int DWSize;
-
- ///
- /// Thread affinity for the created DispatcherQueueController.
- ///
- public int ThreadType;
-
- ///
- /// Specifies whether to initialize COM apartment on the new thread as an application single-threaded apartment (ASTA)
- /// or single-threaded apartment (STA). This field is only relevant if threadType is DQTYPE_THREAD_DEDICATED.
- /// Use DQTAT_COM_NONE when DispatcherQueueOptions.threadType is DQTYPE_THREAD_CURRENT.
- ///
- public int ApartmentType;
- }
-
- [LibraryImport("CoreMessaging.dll")]
- private static unsafe partial int CreateDispatcherQueueController(DispatcherQueueOptions options, nint* instance);
-
- private nint m_dispatcherQueueController = nint.Zero;
- public void EnsureWindowsSystemDispatcherQueueController()
- {
- if (DispatcherQueue.GetForCurrentThread() != null)
- {
- // one already exists, so we'll just use it.
- return;
- }
-
- if (m_dispatcherQueueController == nint.Zero)
- {
- DispatcherQueueOptions options;
- options.DWSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
- options.ThreadType = 2; // DQTYPE_THREAD_CURRENT
- options.ApartmentType = 2; // DQTAT_COM_STA
-
- unsafe
- {
- nint dispatcherQueueController;
- _ = CreateDispatcherQueueController(options, &dispatcherQueueController);
- m_dispatcherQueueController = dispatcherQueueController;
- }
- }
- }
- }
-}
diff --git a/CoreAppUWP/Helpers/SettingsHelper.cs b/CoreAppUWP/Helpers/SettingsHelper.cs
index 7d396f1..277316d 100644
--- a/CoreAppUWP/Helpers/SettingsHelper.cs
+++ b/CoreAppUWP/Helpers/SettingsHelper.cs
@@ -1,5 +1,4 @@
-using CommunityToolkit.WinUI.Helpers;
-using MetroLog;
+using MetroLog;
using MetroLog.Targets;
using Microsoft.UI.Xaml;
using System;
@@ -8,7 +7,6 @@
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Windows.Storage;
-using Windows.UI.ViewManagement;
using IObjectSerializer = CommunityToolkit.Common.Helpers.IObjectSerializer;
namespace CoreAppUWP.Helpers
@@ -43,9 +41,7 @@ public static void SetDefaultSettings()
public static partial class SettingsHelper
{
- public static UISettings UISettings { get; } = new();
public static ILogManager LogManager { get; private set; }
- public static OSVersion OperatingSystemVersion => SystemInformation.Instance.OperatingSystemVersion;
public static ApplicationDataStorageHelper LocalObject { get; } = ApplicationDataStorageHelper.GetCurrent(new SystemTextJsonObjectSerializer());
static SettingsHelper() => SetDefaultSettings();
diff --git a/CoreAppUWP/Helpers/StorageFileHelper.cs b/CoreAppUWP/Helpers/StorageFileHelper.cs
new file mode 100644
index 0000000..8ff38a7
--- /dev/null
+++ b/CoreAppUWP/Helpers/StorageFileHelper.cs
@@ -0,0 +1,697 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.ApplicationModel;
+using Windows.Storage;
+using Windows.Storage.Search;
+using Windows.Storage.Streams;
+
+namespace CoreAppUWP.Helpers
+{
+ ///
+ /// This class provides static helper methods for .
+ ///
+ public static class StorageFileHelper
+ {
+ ///
+ /// Saves a string value to a in application local folder/>.
+ ///
+ ///
+ /// The value to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the text.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteTextToLocalFileAsync(
+ string text,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalFolder;
+ return folder.WriteTextToFileAsync(text, fileName, options);
+ }
+
+ ///
+ /// Saves a string value to a in application local cache folder/>.
+ ///
+ ///
+ /// The value to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the text.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteTextToLocalCacheFileAsync(
+ string text,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
+ return folder.WriteTextToFileAsync(text, fileName, options);
+ }
+
+ ///
+ /// Saves a string value to a in well known folder/>.
+ ///
+ ///
+ /// The well known folder ID to use.
+ ///
+ ///
+ /// The value to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the text.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteTextToKnownFolderFileAsync(
+ KnownFolderId knownFolderId,
+ string text,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = GetFolderFromKnownFolderId(knownFolderId);
+ return folder.WriteTextToFileAsync(text, fileName, options);
+ }
+
+ ///
+ /// Saves a string value to a in the given .
+ ///
+ ///
+ /// The to save the file in.
+ ///
+ ///
+ /// The value to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the text.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static async Task WriteTextToFileAsync(
+ this StorageFolder fileLocation,
+ string text,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (fileLocation == null)
+ {
+ throw new ArgumentNullException(nameof(fileLocation));
+ }
+
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFile storageFile = await fileLocation.CreateFileAsync(fileName, options);
+ await FileIO.WriteTextAsync(storageFile, text);
+
+ return storageFile;
+ }
+
+ ///
+ /// Saves an array of bytes to a to application local folder/>.
+ ///
+ ///
+ /// The array to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the bytes.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteBytesToLocalFileAsync(
+ byte[] bytes,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalFolder;
+ return folder.WriteBytesToFileAsync(bytes, fileName, options);
+ }
+
+ ///
+ /// Saves an array of bytes to a to application local cache folder/>.
+ ///
+ ///
+ /// The array to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the bytes.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteBytesToLocalCacheFileAsync(
+ byte[] bytes,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
+ return folder.WriteBytesToFileAsync(bytes, fileName, options);
+ }
+
+ ///
+ /// Saves an array of bytes to a to well known folder/>.
+ ///
+ ///
+ /// The well known folder ID to use.
+ ///
+ ///
+ /// The array to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the bytes.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static Task WriteBytesToKnownFolderFileAsync(
+ KnownFolderId knownFolderId,
+ byte[] bytes,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = GetFolderFromKnownFolderId(knownFolderId);
+ return folder.WriteBytesToFileAsync(bytes, fileName, options);
+ }
+
+ ///
+ /// Saves an array of bytes to a in the given .
+ ///
+ ///
+ /// The to save the file in.
+ ///
+ ///
+ /// The array to save to the file.
+ ///
+ ///
+ /// The name for the file.
+ ///
+ ///
+ /// The creation collision options. Default is ReplaceExisting.
+ ///
+ ///
+ /// The saved containing the bytes.
+ ///
+ ///
+ /// Exception thrown if the file location or file name are null or empty.
+ ///
+ public static async Task WriteBytesToFileAsync(
+ this StorageFolder fileLocation,
+ byte[] bytes,
+ string fileName,
+ CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+ {
+ if (fileLocation == null)
+ {
+ throw new ArgumentNullException(nameof(fileLocation));
+ }
+
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFile storageFile = await fileLocation.CreateFileAsync(fileName, options);
+ await FileIO.WriteBytesAsync(storageFile, bytes);
+
+ return storageFile;
+ }
+
+ ///
+ /// Gets a string value from a located in the application installation folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored value.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadTextFromPackagedFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = Package.Current.InstalledLocation;
+ return folder.ReadTextFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets a string value from a located in the application local cache folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored value.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadTextFromLocalCacheFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
+ return folder.ReadTextFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets a string value from a located in the application local folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored value.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadTextFromLocalFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalFolder;
+ return folder.ReadTextFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets a string value from a located in a well known folder.
+ ///
+ ///
+ /// The well known folder ID to use.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored value.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadTextFromKnownFoldersFileAsync(
+ KnownFolderId knownFolderId,
+ string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = GetFolderFromKnownFolderId(knownFolderId);
+ return folder.ReadTextFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets a string value from a located in the given .
+ ///
+ ///
+ /// The to save the file in.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored value.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static async Task ReadTextFromFileAsync(
+ this StorageFolder fileLocation,
+ string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFile file = await fileLocation.GetFileAsync(fileName);
+ return await FileIO.ReadTextAsync(file);
+ }
+
+ ///
+ /// Gets an array of bytes from a located in the application installation folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored array.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadBytesFromPackagedFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = Package.Current.InstalledLocation;
+ return folder.ReadBytesFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets an array of bytes from a located in the application local cache folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored array.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadBytesFromLocalCacheFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalCacheFolder;
+ return folder.ReadBytesFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets an array of bytes from a located in the application local folder.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored array.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadBytesFromLocalFileAsync(string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = ApplicationData.Current.LocalFolder;
+ return folder.ReadBytesFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets an array of bytes from a located in a well known folder.
+ ///
+ ///
+ /// The well known folder ID to use.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored array.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static Task ReadBytesFromKnownFoldersFileAsync(
+ KnownFolderId knownFolderId,
+ string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFolder folder = GetFolderFromKnownFolderId(knownFolderId);
+ return folder.ReadBytesFromFileAsync(fileName);
+ }
+
+ ///
+ /// Gets an array of bytes from a located in the given .
+ ///
+ ///
+ /// The to save the file in.
+ ///
+ ///
+ /// The relative file path.
+ ///
+ ///
+ /// The stored array.
+ ///
+ ///
+ /// Exception thrown if the is null or empty.
+ ///
+ public static async Task ReadBytesFromFileAsync(
+ this StorageFolder fileLocation,
+ string fileName)
+ {
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ throw new ArgumentNullException(nameof(fileName));
+ }
+
+ StorageFile file = await fileLocation.GetFileAsync(fileName).AsTask().ConfigureAwait(false);
+ return await file.ReadBytesAsync();
+ }
+
+ ///
+ /// Gets an array of bytes from a .
+ ///
+ ///
+ /// The .
+ ///
+ ///
+ /// The stored array.
+ ///
+ public static async Task ReadBytesAsync(this StorageFile file)
+ {
+ if (file == null)
+ {
+ return null;
+ }
+
+ using IRandomAccessStream stream = await file.OpenReadAsync();
+ using DataReader reader = new(stream.GetInputStreamAt(0));
+ await reader.LoadAsync((uint)stream.Size);
+ byte[] bytes = new byte[stream.Size];
+ reader.ReadBytes(bytes);
+ return bytes;
+ }
+
+ ///
+ /// Gets a value indicating whether a file exists in the current folder.
+ ///
+ ///
+ /// The to look for the file in.
+ ///
+ ///
+ /// The filename of the file to search for. Must include the file extension and is not case-sensitive.
+ ///
+ ///
+ /// The , indicating if the subfolders should also be searched through.
+ ///
+ ///
+ /// true if the file exists; otherwise, false.
+ ///
+ public static Task FileExistsAsync(this StorageFolder folder, string fileName, bool isRecursive = false)
+ => isRecursive
+ ? FileExistsInSubtreeAsync(folder, fileName)
+ : FileExistsInFolderAsync(folder, fileName);
+
+ ///
+ /// Gets a value indicating whether a filename is correct or not using the Storage feature.
+ ///
+ /// The filename to test. Must include the file extension and is not case-sensitive.
+ /// true if the filename is valid; otherwise, false.
+ public static bool IsFileNameValid(string fileName)
+ {
+ char[] illegalChars = Path.GetInvalidFileNameChars();
+ return fileName.All(c => !illegalChars.Contains(c));
+ }
+
+ ///
+ /// Gets a value indicating whether a file path is correct or not using the Storage feature.
+ ///
+ /// The file path to test. Must include the file extension and is not case-sensitive.
+ /// true if the file path is valid; otherwise, false.
+ public static bool IsFilePathValid(string filePath)
+ {
+ char[] illegalChars = Path.GetInvalidPathChars();
+ return filePath.All(c => !illegalChars.Contains(c));
+ }
+
+ ///
+ /// Gets a value indicating whether a file exists in the current folder.
+ ///
+ ///
+ /// The to look for the file in.
+ ///
+ ///
+ /// The filename of the file to search for. Must include the file extension and is not case-sensitive.
+ ///
+ ///
+ /// true if the file exists; otherwise, false.
+ ///
+ internal static async Task FileExistsInFolderAsync(StorageFolder folder, string fileName)
+ {
+ IStorageItem item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false);
+ return (item != null) && item.IsOfType(StorageItemTypes.File);
+ }
+
+ ///
+ /// Gets a value indicating whether a file exists in the current folder or in one of its subfolders.
+ ///
+ ///
+ /// The to look for the file in.
+ ///
+ ///
+ /// The filename of the file to search for. Must include the file extension and is not case-sensitive.
+ ///
+ ///
+ /// true if the file exists; otherwise, false.
+ ///
+ ///
+ /// Exception thrown if the contains a quotation mark.
+ ///
+ internal static async Task FileExistsInSubtreeAsync(StorageFolder rootFolder, string fileName)
+ {
+ if (fileName.IndexOf('"') >= 0)
+ {
+ throw new ArgumentException(nameof(fileName));
+ }
+
+ QueryOptions options = new()
+ {
+ FolderDepth = FolderDepth.Deep,
+ UserSearchFilter = $"filename:=\"{fileName}\"" // “:=” is the exact-match operator
+ };
+
+ IReadOnlyList files = await rootFolder.CreateFileQueryWithOptions(options).GetFilesAsync().AsTask().ConfigureAwait(false);
+ return files.Count > 0;
+ }
+
+ ///
+ /// Returns a from a
+ ///
+ /// Folder Id
+ /// The
+ internal static StorageFolder GetFolderFromKnownFolderId(KnownFolderId knownFolderId)
+ {
+ StorageFolder workingFolder = knownFolderId switch
+ {
+ KnownFolderId.AppCaptures => KnownFolders.AppCaptures,
+ KnownFolderId.CameraRoll => KnownFolders.CameraRoll,
+ KnownFolderId.DocumentsLibrary => KnownFolders.DocumentsLibrary,
+ KnownFolderId.HomeGroup => KnownFolders.HomeGroup,
+ KnownFolderId.MediaServerDevices => KnownFolders.MediaServerDevices,
+ KnownFolderId.MusicLibrary => KnownFolders.MusicLibrary,
+ KnownFolderId.Objects3D => KnownFolders.Objects3D,
+ KnownFolderId.PicturesLibrary => KnownFolders.PicturesLibrary,
+ KnownFolderId.Playlists => KnownFolders.Playlists,
+ KnownFolderId.RecordedCalls => KnownFolders.RecordedCalls,
+ KnownFolderId.RemovableDevices => KnownFolders.RemovableDevices,
+ KnownFolderId.SavedPictures => KnownFolders.SavedPictures,
+ KnownFolderId.VideosLibrary => KnownFolders.VideosLibrary,
+ _ => throw new ArgumentOutOfRangeException(nameof(knownFolderId), knownFolderId, null),
+ };
+ return workingFolder;
+ }
+ }
+}
diff --git a/CoreAppUWP/Pages/HomePage.xaml b/CoreAppUWP/Pages/HomePage.xaml
index 924f55a..21d51cd 100644
--- a/CoreAppUWP/Pages/HomePage.xaml
+++ b/CoreAppUWP/Pages/HomePage.xaml
@@ -2,7 +2,7 @@
x:Class="CoreAppUWP.Pages.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
+ xmlns:cwuc="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
NavigationCacheMode="Enabled"
diff --git a/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml b/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml
index c96e9aa..3007a43 100644
--- a/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml
+++ b/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml
@@ -3,11 +3,13 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
+ xmlns:clwm="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
xmlns:common="using:CoreAppUWP.Common"
xmlns:controls="using:CoreAppUWP.Controls"
- xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
- xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
+ xmlns:converters="using:CommunityToolkit.WinUI.Converters"
+ xmlns:cwuc="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:helpers="using:CoreAppUWP.Helpers"
xmlns:interopservices="using:System.Runtime.InteropServices"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:settingspages="using:CoreAppUWP.ViewModels.SettingsPages"
@@ -41,43 +43,46 @@
-
-
+
+
+
+
+
-
+
-
-
+
+
+
+
+
Mica
MicaAlt
Acrylic
DefaultColor
-
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -150,9 +161,9 @@
-
-
-
+
+
-
+
@@ -170,14 +181,14 @@
-
-
+
+
-
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml.cs b/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml.cs
index fc74009..616f59b 100644
--- a/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml.cs
+++ b/CoreAppUWP/Pages/SettingsPages/SettingsPage.xaml.cs
@@ -1,4 +1,3 @@
-using CommunityToolkit.WinUI.UI.Controls;
using CoreAppUWP.Common;
using CoreAppUWP.Controls;
using CoreAppUWP.Helpers;
@@ -173,7 +172,5 @@ private async void HyperlinkButton_Click(object sender, RoutedEventArgs e)
}
public Task Refresh(bool reset = false) => Provider.Refresh(reset);
-
- private void MarkdownText_LinkClicked(object sender, LinkClickedEventArgs e) => _ = Launcher.LaunchUriAsync(new Uri(e.Link));
}
}
diff --git a/CoreAppUWP/Program.cs b/CoreAppUWP/Program.cs
index ec4a4c8..ab99616 100644
--- a/CoreAppUWP/Program.cs
+++ b/CoreAppUWP/Program.cs
@@ -44,7 +44,7 @@ private static bool IsSupportCoreWindow
try
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\WinUI\Xaml");
- return registryKey?.GetValue("EnableUWPWindow") is int value && value > 0;
+ return registryKey?.GetValue("EnableUWPWindow") is > 0;
}
catch
{
diff --git a/CoreAppUWP/Styles/SettingsCard.xaml b/CoreAppUWP/Styles/SettingsCard.xaml
new file mode 100644
index 0000000..ad32294
--- /dev/null
+++ b/CoreAppUWP/Styles/SettingsCard.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CoreAppUWP/Themes/CustomStyles.xaml b/CoreAppUWP/Themes/CustomStyles.xaml
index 4690d0e..7741fa9 100644
--- a/CoreAppUWP/Themes/CustomStyles.xaml
+++ b/CoreAppUWP/Themes/CustomStyles.xaml
@@ -1,7 +1,6 @@
-
-
+
diff --git a/CoreAppUWP/Themes/Generic.xaml b/CoreAppUWP/Themes/Generic.xaml
index 3d2cae4..3138497 100644
--- a/CoreAppUWP/Themes/Generic.xaml
+++ b/CoreAppUWP/Themes/Generic.xaml
@@ -1,8 +1,6 @@
-
-
diff --git a/nuget.config b/nuget.config
new file mode 100644
index 0000000..8bf43a4
--- /dev/null
+++ b/nuget.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file