diff --git a/BrightSharp.Ui.Tests/App.xaml b/BrightSharp.Ui.Tests/App.xaml index ae7600d..b71f081 100644 --- a/BrightSharp.Ui.Tests/App.xaml +++ b/BrightSharp.Ui.Tests/App.xaml @@ -5,6 +5,7 @@ + diff --git a/BrightSharp.Ui.Tests/App.xaml.cs b/BrightSharp.Ui.Tests/App.xaml.cs index 7c5978c..7c4d708 100644 --- a/BrightSharp.Ui.Tests/App.xaml.cs +++ b/BrightSharp.Ui.Tests/App.xaml.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; namespace BrightSharp.Ui.Tests { diff --git a/BrightSharp.Ui.Tests/BrightSharp.Ui.Tests.csproj b/BrightSharp.Ui.Tests/BrightSharp.Ui.Tests.csproj index 139b013..9f77edf 100644 --- a/BrightSharp.Ui.Tests/BrightSharp.Ui.Tests.csproj +++ b/BrightSharp.Ui.Tests/BrightSharp.Ui.Tests.csproj @@ -136,6 +136,14 @@ BrightSharp + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BrightSharp/Themes/Style.Classic.xaml b/BrightSharp/Themes/Style.Classic.xaml new file mode 100644 index 0000000..5b87557 --- /dev/null +++ b/BrightSharp/Themes/Style.Classic.xaml @@ -0,0 +1,283 @@ + + + + + + 1 + 3 + + 0,8,0,0 + 0,2,2,2 + 0,5,5,0 + 5,0,0,5 + 5,5,0,0 + + Red + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #FFF + + + + + + + Black + + + + + + + + + + + + + + Black + + #DEE4FF + #FFB6B6B6 + #FFFFFFFF + #FFC5C5C5 + #FF6B6B6B + #FFDADCEC + #FF47909B + #D6D6D6 + #E6E6E6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BrightSharp/Themes/Style.DarkBlue.xaml b/BrightSharp/Themes/Style.DarkBlue.xaml index 8bc0a82..ac18d2a 100644 --- a/BrightSharp/Themes/Style.DarkBlue.xaml +++ b/BrightSharp/Themes/Style.DarkBlue.xaml @@ -22,6 +22,8 @@ #FF414888 #FF47909B + #D6D6D6 + #E6E6E6 #FF3333 @@ -80,6 +82,7 @@ + @@ -299,6 +302,6 @@ - - + + \ No newline at end of file diff --git a/BrightSharp/Themes/Style.DevLab.xaml b/BrightSharp/Themes/Style.DevLab.xaml index 36fa265..0b422c5 100644 --- a/BrightSharp/Themes/Style.DevLab.xaml +++ b/BrightSharp/Themes/Style.DevLab.xaml @@ -219,7 +219,8 @@ - + + #E3E3E3 @@ -230,7 +231,45 @@ #FFEEEEEE #FF47909B + #D6D6D6 + #E6E6E6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BrightSharp/Themes/Style.Silver.xaml b/BrightSharp/Themes/Style.Silver.xaml index 4102abb..a0e1f31 100644 --- a/BrightSharp/Themes/Style.Silver.xaml +++ b/BrightSharp/Themes/Style.Silver.xaml @@ -248,7 +248,8 @@ - + + @@ -283,7 +284,41 @@ #FFCED0E1 #FF47909B - - + #D6D6D6 + #E6E6E6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BrightSharp/Themes/Theme.Static.cs b/BrightSharp/Themes/Theme.Static.cs new file mode 100644 index 0000000..574476a --- /dev/null +++ b/BrightSharp/Themes/Theme.Static.cs @@ -0,0 +1,41 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; + +namespace BrightSharp.Themes +{ + + internal partial class ThemeStatic + { + public void CalendarPreviewMouseUp(object sender, MouseEventArgs e) { + if (Mouse.Captured is CalendarItem) { Mouse.Capture(null); } + } + public void DatePickerUnloaded(object sender, RoutedEventArgs e) { + if (sender == null) return; + DependencyObject child = ((Popup)((DatePicker)sender).Template.FindName("PART_Popup", (FrameworkElement)sender))?.Child; + while (child != null && !(child is AdornerDecorator)) + child = VisualTreeHelper.GetParent(child) ?? LogicalTreeHelper.GetParent(child); + if (((AdornerDecorator)child)?.Child is Calendar) ((AdornerDecorator)child).Child = null; + } + + + private void closeButton_Click(object sender, RoutedEventArgs e) { + var window = Window.GetWindow((DependencyObject)sender); + window.Close(); + } + + private void maximizeButton_Click(object sender, RoutedEventArgs e) { + var window = Window.GetWindow((DependencyObject)sender); + window.WindowState = window.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal; + } + + private void minimizeButton_Click(object sender, RoutedEventArgs e) { + var window = Window.GetWindow((DependencyObject)sender); + window.WindowState = WindowState.Minimized; + } + } +} diff --git a/BrightSharp/Themes/Theme.Static.xaml b/BrightSharp/Themes/Theme.Static.xaml new file mode 100644 index 0000000..c7eb0bd --- /dev/null +++ b/BrightSharp/Themes/Theme.Static.xaml @@ -0,0 +1,5729 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BrightSharp/Themes/Theme.cs b/BrightSharp/Themes/Theme.cs index 07e1e10..219a1a3 100644 --- a/BrightSharp/Themes/Theme.cs +++ b/BrightSharp/Themes/Theme.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; @@ -8,19 +7,13 @@ using System.Windows.Media; namespace BrightSharp.Themes { + internal partial class Theme { - public Theme() { - - - } - - public void CalendarPreviewMouseUp(object sender, MouseEventArgs e) - { + public void CalendarPreviewMouseUp(object sender, MouseEventArgs e) { if (Mouse.Captured is CalendarItem) { Mouse.Capture(null); } } - public void DatePickerUnloaded(object sender, RoutedEventArgs e) - { + public void DatePickerUnloaded(object sender, RoutedEventArgs e) { if (sender == null) return; DependencyObject child = ((Popup)((DatePicker)sender).Template.FindName("PART_Popup", (FrameworkElement)sender))?.Child; while (child != null && !(child is AdornerDecorator)) @@ -29,23 +22,19 @@ namespace BrightSharp.Themes } - private void closeButton_Click(object sender, RoutedEventArgs e) - { + private void closeButton_Click(object sender, RoutedEventArgs e) { var window = Window.GetWindow((DependencyObject)sender); window.Close(); } - private void maximizeButton_Click(object sender, RoutedEventArgs e) - { + private void maximizeButton_Click(object sender, RoutedEventArgs e) { var window = Window.GetWindow((DependencyObject)sender); window.WindowState = window.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal; } - private void minimizeButton_Click(object sender, RoutedEventArgs e) - { + private void minimizeButton_Click(object sender, RoutedEventArgs e) { var window = Window.GetWindow((DependencyObject)sender); window.WindowState = WindowState.Minimized; } - } } diff --git a/BrightSharp/Themes/Theme.xaml b/BrightSharp/Themes/Theme.xaml index f0fbab1..da1d3a8 100644 --- a/BrightSharp/Themes/Theme.xaml +++ b/BrightSharp/Themes/Theme.xaml @@ -1,14 +1,16 @@ - + xmlns:bs="clr-namespace:BrightSharp.Extensions" + xmlns:conv="clr-namespace:BrightSharp.Converters"> - + + @@ -17,284 +19,9 @@ - - - 1 - 3 - - 0,8,0,0 - 0,2,2,2 - 0,5,5,0 - 5,0,0,5 - 5,5,0,0 - - Red - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #FFF - - - - - - - Black - - - - - - - - - - - - - - Black - - #DEE4FF - #FFB6B6B6 - #FFFFFFFF - #FFC5C5C5 - #FF6B6B6B - #FFDADCEC - #FF47909B - #D6D6D6 - #E6E6E6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -5999,4 +5726,5 @@ + \ No newline at end of file diff --git a/BrightSharp/Themes/ThemeManager.cs b/BrightSharp/Themes/ThemeManager.cs index 9f077fb..dd15ee1 100644 --- a/BrightSharp/Themes/ThemeManager.cs +++ b/BrightSharp/Themes/ThemeManager.cs @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Windows; +using System.Windows.Threading; namespace BrightSharp.Themes { public enum ColorThemes { + None, Classic, DevLab, Silver, @@ -18,30 +20,53 @@ namespace BrightSharp.Themes public static class ThemeManager { private const string StyleDictionaryPattern = @"(?<=.+style\.)(.*?)(?=\.xaml)"; + private const string StaticThemeDictionaryUri = "/brightsharp;component/themes/theme.static.xaml"; + + static ColorThemes? _theme; + public static ColorThemes Theme { - get - { + get { + if (_theme.HasValue) return _theme.Value; var curStyleRes = Resources.Where(r => r.Source != null && - Regex.IsMatch(r.Source.OriginalString, StyleDictionaryPattern, RegexOptions.IgnoreCase)).FirstOrDefault(); - if (curStyleRes == null) return ColorThemes.Classic; + Regex.IsMatch(r.Source.OriginalString, StyleDictionaryPattern, RegexOptions.IgnoreCase)).FirstOrDefault(); + if (curStyleRes == null) return ColorThemes.None; var match = Regex.Match(curStyleRes.Source.OriginalString, StyleDictionaryPattern, RegexOptions.IgnoreCase); - return (ColorThemes)Enum.Parse(typeof(ColorThemes), match.Value, true); + _theme = (ColorThemes)Enum.Parse(typeof(ColorThemes), match.Value, true); + return _theme.Value; } - set - { - var curStyleRes = Resources.Where(r => r.Source != null && - Regex.IsMatch(r.Source.OriginalString, StyleDictionaryPattern, RegexOptions.IgnoreCase)).FirstOrDefault(); - if (curStyleRes != null) - Resources.Remove(curStyleRes); - if (value == ColorThemes.Classic) - return; - Resources.Add(new ResourceDictionary() - { - Source = new Uri($"/brightsharp;component/themes/style.{value}.xaml", UriKind.RelativeOrAbsolute) - }); + set { + SetTheme(value); } } + + public static DispatcherOperation SetTheme(ColorThemes value, DispatcherPriority priority = DispatcherPriority.Background) { + if (_theme == value) return Application.Current.Dispatcher.BeginInvoke(new Action(() => { }), priority); + _theme = value; + return Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (_theme != value) return; + Application.Current.Resources.BeginInit(); + + var curStyleRes = Resources.Where(r => r.Source != null && + Regex.IsMatch(r.Source.OriginalString, StyleDictionaryPattern, RegexOptions.IgnoreCase)).FirstOrDefault(); + var curThemeRes = Resources.Where(r => r.Source != null && r.Source.OriginalString.Equals(StaticThemeDictionaryUri, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); + if (curThemeRes != null) + Resources.Remove(curThemeRes); + if (curStyleRes != null) + Resources.Remove(curStyleRes); + if (value == ColorThemes.None) return; + Resources.Add(new ResourceDictionary() { Source = new Uri($"/brightsharp;component/themes/style.{value}.xaml", UriKind.RelativeOrAbsolute) }); + if (curThemeRes != null) + Resources.Add(new ResourceDictionary() { Source = new Uri(StaticThemeDictionaryUri, UriKind.RelativeOrAbsolute) }); + + Application.Current.Resources.EndInit(); + ThemeChanged?.Invoke(null, EventArgs.Empty); + }), priority); + } + + public static event EventHandler ThemeChanged; + private static ICollection Resources { get { return Application.Current.Resources.MergedDictionaries; } diff --git a/README.md b/README.md index 250934d..b1279a4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Professional WPF Themes and User Controls. It requires `.NET 4.5`. -### Current Version 2.0 +### Current Version 2.1 ### Nuget diff --git a/docs/help/apply-themes.md b/docs/help/apply-themes.md index ea67ea1..6095124 100644 --- a/docs/help/apply-themes.md +++ b/docs/help/apply-themes.md @@ -4,7 +4,9 @@ ```xml - + + + @@ -15,7 +17,7 @@ Change by `ThemeManager` ```c# - ThemeManager.CurrentTheme = ColorThemes.Classic; + ThemeManager.CurrentTheme = ColorThemes.DarkBlue; ``` # Change themes by ResourceDictionary @@ -23,12 +25,15 @@ Change by `ThemeManager` As default we use Classic theme. You also can change theme by adding resource dictionary after generic.xaml. Use one of them: ```xml - - - - + + + + + ``` -## NOTE +## NOTES You can use custom window style named `BrightSharpWindowStyle`. -Also defined additional useful styles and extensions. For more info see Demo source code. \ No newline at end of file +Also defined additional useful styles and extensions. For more info see Demo source code. + + \ No newline at end of file