diff --git a/README.md b/README.md
index 4f6cacb..ec46e72 100644
--- a/README.md
+++ b/README.md
@@ -148,6 +148,7 @@ Install-Package DevWinUI
## 🔥 DevWinUI.Controls 🔥
### ⚡ What’s Inside? ⚡
+- ✨ ProgressButton
- ✨ TextBox
- ✨ BreadcrumbNavigator
- ✨ PinBox
@@ -246,6 +247,9 @@ Install-Package DevWinUI.ContextMenu
## 🕰️ History 🕰️
+### ProgressButton
+![DevWinUI](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/ProgressButton.png)
+
### TextBox
![DevWinUI](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/TextBox.png)
diff --git a/dev/DevWinUI.Controls/Controls/ProgressButton.cs b/dev/DevWinUI.Controls/Controls/ProgressButton.cs
new file mode 100644
index 0000000..326b0e7
--- /dev/null
+++ b/dev/DevWinUI.Controls/Controls/ProgressButton.cs
@@ -0,0 +1,153 @@
+using Microsoft.UI.Xaml.Controls.Primitives;
+
+namespace DevWinUI;
+
+[TemplatePart(Name = nameof(PART_ProgressBar), Type = typeof(ProgressBar))]
+public partial class ProgressButton : ToggleButton
+{
+ private readonly string PART_ProgressBar = "PART_ProgressBar";
+ private ProgressBar progressBar;
+
+ public SolidColorBrush ProgressBackground
+ {
+ get { return (SolidColorBrush)GetValue(ProgressBackgroundProperty); }
+ set { SetValue(ProgressBackgroundProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressBackgroundProperty =
+ DependencyProperty.Register(nameof(ProgressBackground), typeof(SolidColorBrush), typeof(ProgressButton), new PropertyMetadata(null));
+
+ public SolidColorBrush ProgressForeground
+ {
+ get { return (SolidColorBrush)GetValue(ProgressForegroundProperty); }
+ set { SetValue(ProgressForegroundProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressForegroundProperty =
+ DependencyProperty.Register(nameof(ProgressForeground), typeof(SolidColorBrush), typeof(ProgressButton), new PropertyMetadata(null));
+
+ public HorizontalAlignment ProgressRingHorizontalAlignment
+ {
+ get { return (HorizontalAlignment)GetValue(ProgressRingHorizontalAlignmentProperty); }
+ set { SetValue(ProgressRingHorizontalAlignmentProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressRingHorizontalAlignmentProperty =
+ DependencyProperty.Register(nameof(ProgressRingHorizontalAlignment), typeof(HorizontalAlignment), typeof(ProgressButton), new PropertyMetadata(HorizontalAlignment.Right));
+
+ public double ProgressRingSize
+ {
+ get { return (double)GetValue(ProgressRingSizeProperty); }
+ set { SetValue(ProgressRingSizeProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressRingSizeProperty =
+ DependencyProperty.Register(nameof(ProgressRingSize), typeof(double), typeof(ProgressButton), new PropertyMetadata(24.0));
+
+ public Visibility ProgressRingVisibility
+ {
+ get { return (Visibility)GetValue(ProgressRingVisibilityProperty); }
+ set { SetValue(ProgressRingVisibilityProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressRingVisibilityProperty =
+ DependencyProperty.Register(nameof(ProgressRingVisibility), typeof(Visibility), typeof(ProgressButton), new PropertyMetadata(Visibility.Collapsed));
+
+ public bool IsIndeterminateProgressRing
+ {
+ get { return (bool)GetValue(IsIndeterminateProgressRingProperty); }
+ set { SetValue(IsIndeterminateProgressRingProperty, value); }
+ }
+
+ public static readonly DependencyProperty IsIndeterminateProgressRingProperty =
+ DependencyProperty.Register(nameof(IsIndeterminateProgressRing), typeof(bool), typeof(ProgressButton), new PropertyMetadata(true));
+
+ public Style ProgressRingStyle
+ {
+ get => (Style)GetValue(ProgressRingStyleProperty);
+ set => SetValue(ProgressRingStyleProperty, value);
+ }
+
+ public static readonly DependencyProperty ProgressRingStyleProperty = DependencyProperty.Register(
+ nameof(ProgressRingStyle), typeof(Style), typeof(ProgressButton), new PropertyMetadata(default(Style)));
+
+ public double Progress
+ {
+ get { return (double)GetValue(ProgressProperty); }
+ set { SetValue(ProgressProperty, value); }
+ }
+
+ public static readonly DependencyProperty ProgressProperty =
+ DependencyProperty.Register(nameof(Progress), typeof(double), typeof(ProgressButton), new PropertyMetadata(0.0));
+
+ public object CheckedContent
+ {
+ get { return (object)GetValue(CheckedContentProperty); }
+ set { SetValue(CheckedContentProperty, value); }
+ }
+
+ public static readonly DependencyProperty CheckedContentProperty =
+ DependencyProperty.Register(nameof(CheckedContent), typeof(object), typeof(ProgressButton), new PropertyMetadata(default(object)));
+
+ public bool ShowError
+ {
+ get { return (bool)GetValue(ShowErrorProperty); }
+ set { SetValue(ShowErrorProperty, value); }
+ }
+
+ public static readonly DependencyProperty ShowErrorProperty =
+ DependencyProperty.Register(nameof(ShowError), typeof(bool), typeof(ProgressButton), new PropertyMetadata(false));
+
+ public bool ShowPaused
+ {
+ get { return (bool)GetValue(ShowPausedProperty); }
+ set { SetValue(ShowPausedProperty, value); }
+ }
+
+ public static readonly DependencyProperty ShowPausedProperty =
+ DependencyProperty.Register(nameof(ShowPaused), typeof(bool), typeof(ProgressButton), new PropertyMetadata(false));
+
+ public bool IsIndeterminate
+ {
+ get { return (bool)GetValue(IsIndeterminateProperty); }
+ set { SetValue(IsIndeterminateProperty, value); }
+ }
+
+ public static readonly DependencyProperty IsIndeterminateProperty =
+ DependencyProperty.Register(nameof(IsIndeterminate), typeof(bool), typeof(ProgressButton), new PropertyMetadata(false));
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ SizeChanged += ProgressButton_SizeChanged;
+ progressBar = GetTemplateChild(nameof(PART_ProgressBar)) as ProgressBar;
+ if (progressBar != null)
+ {
+ progressBar.MinHeight = ActualHeight;
+ progressBar.Loaded += ProgressBar_Loaded;
+ }
+ }
+
+ private void ProgressBar_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (progressBar != null)
+ {
+ progressBar.ApplyTemplate();
+ var track = progressBar.FindDescendant("ProgressBarTrack");
+ if (track != null)
+ {
+ track.VerticalAlignment = VerticalAlignment.Stretch;
+ track.Height = double.NaN;
+ }
+ }
+ }
+
+ private void ProgressButton_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (progressBar != null)
+ {
+ progressBar.MinHeight = ActualHeight;
+ }
+ }
+}
diff --git a/dev/DevWinUI.Controls/Themes/Generic.xaml b/dev/DevWinUI.Controls/Themes/Generic.xaml
index 4499cf7..ce9b928 100644
--- a/dev/DevWinUI.Controls/Themes/Generic.xaml
+++ b/dev/DevWinUI.Controls/Themes/Generic.xaml
@@ -27,6 +27,7 @@ Themes\Styles\Controls\LoadingIndicator.xaml
Themes\Styles\Controls\LongShadowTextBlock.xaml
Themes\Styles\Controls\OptionsPageControl.xaml
Themes\Styles\Controls\PinBox.xaml
+Themes\Styles\Controls\ProgressButton.xaml
Themes\Styles\Controls\ProgressRing.xaml
Themes\Styles\Controls\RedirectVisualView.xaml
Themes\Styles\Controls\SelectorBarSegmented.xaml
@@ -86,6 +87,7 @@ Themes\Styles\Win2D\Watermark.xaml
+
@@ -149,6 +151,7 @@ Themes\Styles\Win2D\Watermark.xaml
+
@@ -209,6 +212,7 @@ Themes\Styles\Win2D\Watermark.xaml
+
@@ -3332,6 +3336,214 @@ Themes\Styles\Win2D\Watermark.xaml
+
+
diff --git a/dev/DevWinUI.Gallery/Assets/Fluent/ToggleButton.png b/dev/DevWinUI.Gallery/Assets/Fluent/ToggleButton.png
new file mode 100644
index 0000000..52682aa
Binary files /dev/null and b/dev/DevWinUI.Gallery/Assets/Fluent/ToggleButton.png differ
diff --git a/dev/DevWinUI.Gallery/Assets/NavViewMenu/AppData.json b/dev/DevWinUI.Gallery/Assets/NavViewMenu/AppData.json
index 50dded3..6d7dfde 100644
--- a/dev/DevWinUI.Gallery/Assets/NavViewMenu/AppData.json
+++ b/dev/DevWinUI.Gallery/Assets/NavViewMenu/AppData.json
@@ -94,6 +94,13 @@
"ImagePath": "ms-appx:///Assets/Fluent/RatingControl.png",
"IsSpecialSection": false,
"Items": [
+ {
+ "UniqueId": "DevWinUIGallery.Views.ProgressButtonPage",
+ "Title": "ProgressButton",
+ "Subtitle": "ProgressButton",
+ "IsNew": true,
+ "ImagePath": "ms-appx:///Assets/Fluent/ToggleButton.png"
+ },
{
"UniqueId": "DevWinUIGallery.Views.TextBoxPage",
"Title": "TextBox",
diff --git a/dev/DevWinUI.Gallery/T4Templates/NavigationPageMappings.cs b/dev/DevWinUI.Gallery/T4Templates/NavigationPageMappings.cs
index 2160385..fa1d9c2 100644
--- a/dev/DevWinUI.Gallery/T4Templates/NavigationPageMappings.cs
+++ b/dev/DevWinUI.Gallery/T4Templates/NavigationPageMappings.cs
@@ -25,6 +25,7 @@ public partial class NavigationPageMappings
{"DevWinUIGallery.Views.WaveCirclePage", typeof(DevWinUIGallery.Views.WaveCirclePage)},
{"DevWinUIGallery.Views.BubblePage", typeof(DevWinUIGallery.Views.BubblePage)},
{"DevWinUIGallery.Views.GooeyPage", typeof(DevWinUIGallery.Views.GooeyPage)},
+ {"DevWinUIGallery.Views.ProgressButtonPage", typeof(DevWinUIGallery.Views.ProgressButtonPage)},
{"DevWinUIGallery.Views.TextBoxPage", typeof(DevWinUIGallery.Views.TextBoxPage)},
{"DevWinUIGallery.Views.TileControlPage", typeof(DevWinUIGallery.Views.TileControlPage)},
{"DevWinUIGallery.Views.PinBoxPage", typeof(DevWinUIGallery.Views.PinBoxPage)},
diff --git a/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml b/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml
new file mode 100644
index 0000000..6f1b6fe
--- /dev/null
+++ b/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+ <dev:ProgressButton CheckedContent="Downloading..." Content="Click Here" IsIndeterminateProgressRing="true" ProgressRingVisibility="Visible" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml.cs b/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml.cs
new file mode 100644
index 0000000..4747b5e
--- /dev/null
+++ b/dev/DevWinUI.Gallery/Views/Pages/Features/ProgressButtonPage.xaml.cs
@@ -0,0 +1,28 @@
+namespace DevWinUIGallery.Views;
+
+public sealed partial class ProgressButtonPage : Page
+{
+ public ProgressButtonPage()
+ {
+ this.InitializeComponent();
+ }
+
+ private async void ProgressButton_Checked(object sender, RoutedEventArgs e)
+ {
+ var pb = sender as ProgressButton;
+ if (pb.IsChecked.Value && !pb.IsIndeterminate)
+ {
+ pb.Progress = 0;
+ while (true)
+ {
+ pb.Progress += 1;
+ await Task.Delay(50);
+ if (pb.Progress == 100)
+ {
+ pb.IsChecked = false;
+ break;
+ }
+ }
+ }
+ }
+}