[C#/WINUI3/COMMUNITY TOOLKIT/.NET8] ThemeListener 클래스 : ThemeChanged 이벤트를 사용해 현재 테마 변경시 처리하기
■ ThemeListener 클래스의 ThemeChanged 이벤트를 사용해 현재 테마 변경시 처리하는 방법을 보여준다. ※ 비주얼 스튜디오에서 TestProject(Unpackaged) 모드로 빌드한다. ※ TestProject.csproj 프로젝트 파일에서
■ ThemeListener 클래스의 ThemeChanged 이벤트를 사용해 현재 테마 변경시 처리하는 방법을 보여준다. ※ 비주얼 스튜디오에서 TestProject(Unpackaged) 모드로 빌드한다. ※ TestProject.csproj 프로젝트 파일에서
■ Button 엘리먼트의 Style 속성을 사용해 버튼 스타일을 설정하는 방법을 보여준다. ※ 비주얼 스튜디오에서 TestProject(Unpackaged) 모드로 빌드한다. ※ TestProject.csproj 프로젝트 파일에서 WindowsPackageType
■ IAppInfo 인터페이스의 ShowSettingsUI 메소드를 사용해 앱 설정을 표시하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 |
AppInfo.Current.ShowSettingsUI(); |
■ IAppInfo 인터페이스의 RequestedTheme 속성을 사용해 현재 테마를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 |
AppTheme appTheme = AppInfo.Current.RequestedTheme; |
■ Application 클래스의 RequestedThemeChanged 이벤트를 사용해 현재 테마 변경시 처리하는 방법을 보여준다. ▶ Platforms/Android/MainActivity.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
using Android.App; using Android.Content.PM; using Android.OS; namespace TestProject; /// <summary> /// 메인 액티비티 /// </summary> [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { } |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Label x:Name="label" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" FontSize="48" /> </ContentPage> |
▶ MainPage.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
namespace TestProject; /// <summary> /// 메인 페이지 /// </summary> public partial class MainPage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); Application application = Application.Current; application.RequestedThemeChanged += application_RequestedThemeChanged; Loaded += ContentPage_Loaded; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 애플리케이션 요청 테마 변경시 처리하기 - application_RequestedThemeChanged(sender, e) /// <summary> /// 애플리케이션 요청 테마 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void application_RequestedThemeChanged(object sender, AppThemeChangedEventArgs e) { ChangeTheme(e.RequestedTheme); } #endregion #region 컨텐트 페이지 로드시 처리하기 - ContentPage_Loaded(sender, e) /// <summary> /// 컨텐트 페이지 로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void ContentPage_Loaded(object sender, EventArgs e) { ChangeTheme(Application.Current.RequestedTheme); } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 테마 변경하기 - ChangeTheme(theme) /// <summary> /// 테마 변경하기 /// </summary> /// <param name="theme">테마</param> private void ChangeTheme(AppTheme theme) { if(theme == AppTheme.Light) { BackgroundColor = Colors.White; this.label.TextColor = Colors.Black; } else { BackgroundColor = Colors.Black; this.label.TextColor = Colors.White; } this.label.Text = theme.ToString(); } #endregion } |
TestProject.zip
■ Application 클래스의 UserAppTheme 속성을 사용해 사용자 테마를 설정하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 |
Application.Current.UserAppTheme = AppTheme.Dark; |
※ 앱에서 사용하는 테마는 현재 작동
■ Application 클래스의 RequestedTheme 속성을 사용해 현재 테마를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 |
AppTheme currentTheme = Application.Current.RequestedTheme; |
■ BindableObjectExtensions 클래스의 SetAppThemeColor 확장 메소드를 사용해 앱 테마 색상을 설정하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 |
Label label; ... label.SetAppThemeColor(Label.TextColorProperty, Colors.Green, Colors.Red); |
■ BindableObjectExtensions 클래스의 SetAppTheme<T> 확장 메소드를 사용해 앱 테마를 설정하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 |
Image image; ... image.SetAppTheme<FileImageSource>(Image.SourceProperty, "lightlogo.png", "darklogo.png"); |
■ 런타임에서 테마를 변경하는 방법을 보여준다. ▶ LightThemeDictionary.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8" ?> <ResourceDictionary x:Class="TestProject.Themes.LightThemeDictionary" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Color x:Key="PageBackgroundColorKey">White</Color> <Color x:Key="NavigationBarColorKey">WhiteSmoke</Color> <Color x:Key="PrimaryColorKey">WhiteSmoke</Color> <Color x:Key="SecondaryColorKey">Black</Color> <Color x:Key="PrimaryTextColorKey">Black</Color> <Color x:Key="SecondaryTextColorKey">White</Color> <Color x:Key="TertiaryTextColorKey">Gray</Color> <Color x:Key="TransparentColorKey">Transparent</Color> </ResourceDictionary> |
▶ LightThemeDictionary.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace TestProject.Themes; public partial class LightThemeDictionary : ResourceDictionary { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - LightThemeDictionary() /// <summary> /// 생성자 /// </summary> public LightThemeDictionary() { InitializeComponent(); } #endregion } |
▶ DarkThemeDictionary.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8" ?> <ResourceDictionary x:Class="TestProject.Themes.DarkThemeDictionary" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Color x:Key="PageBackgroundColorKey">Black</Color> <Color x:Key="NavigationBarColorKey">Teal</Color> <Color x:Key="PrimaryColorKey">Teal</Color> <Color x:Key="SecondaryColorKey">White</Color> <Color x:Key="PrimaryTextColorKey">White</Color> <Color x:Key="SecondaryTextColorKey">White</Color> <Color x:Key="TertiaryTextColorKey">WhiteSmoke</Color> <Color x:Key="TransparentColorKey">Transparent</Color> </ResourceDictionary> |
▶ DarkThemeDictionary.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace TestProject.Themes; public partial class DarkThemeDictionary : ResourceDictionary { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - DarkThemeDictionary() /// <summary> /// 생성자 /// </summary> public DarkThemeDictionary() { InitializeComponent(); } #endregion } |
▶ App.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version = "1.0" encoding = "UTF-8" ?> <Application x:Class="TestProject.App" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Application.Resources> <ResourceDictionary Source="Themes/LightThemeDictionary.xaml" /> <Style x:Key="LargeLabelStyleKey" TargetType="Label"> <Setter Property="TextColor" Value="{DynamicResource SecondaryTextColorKey}" /> <Setter Property="FontSize" Value="30" /> </Style> <Style x:Key="MediumLabelStyleKey" TargetType="Label"> <Setter Property="TextColor" Value="{DynamicResource PrimaryTextColorKey}" /> <Setter Property="FontSize" Value="25" /> </Style> <Style x:Key="SmallLabelStyleKey" TargetType="Label"> <Setter Property="TextColor" Value="{DynamicResource TertiaryTextColorKey}" /> <Setter Property="FontSize" Value="15" /> </Style> </Application.Resources> </Application> |
▶
■ ThemeEditor 클래스를 사용해 차트 테마를 설정하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Drawing; using Steema.TeeChart.Editors; using Steema.TeeChart.Styles; using Steema.TeeChart.Themes; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 테마 에디터 /// </summary> private ThemeEditor themeEditor; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); Text = "ThemeEditor 클래스 : 차트 테마 설정하기"; this.tChart.Panel.Pen = new ChartPen(Color.Black); Bar bar = new Bar(this.tChart.Chart); bar.ColorEach = true; bar.FillSampleValues(); this.themeEditor = new ThemeEditor(this.tChart.Chart, null); object[] objectCollection; this.themeEditor.AddChartThemes(out objectCollection); this.themeListBox.DisplayMember = "Name"; this.themeListBox.Items.Clear(); foreach(object item in objectCollection) { this.themeListBox.Items.Add ( new ThemeItem { Name = item.GetType().ToString().Replace("Steema.TeeChart.Themes.", string.Empty), Theme = item as Theme } ); } this.themeListBox.SelectedIndexChanged += themeListBox_SelectedIndexChanged; this.themeEditorButton.Click += themeEditorButton_Click; this.applyByCodeButton.Click += applyByCodeButton_Click; this.themeListBox.SelectedIndex = 0; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 테마 리스트 박스 선택 인덱스 변경시 처리하기 - themeListBox_SelectedIndexChanged(sender, e) /// <summary> /// 테마 리스트 박스 선택 인덱스 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void themeListBox_SelectedIndexChanged(object sender, EventArgs e) { if(this.themeListBox.SelectedIndex != -1) { ThemeItem item = this.themeListBox.SelectedItem as ThemeItem; item.Theme.Apply(); } } #endregion #region 테마 에디터 버튼 클릭시 처리하기 - themeEditorButton_Click(sender, e) /// <summary> /// 테마 에디터 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void themeEditorButton_Click(object sender, EventArgs e) { this.themeEditor.ShowDialog(); this.themeListBox.SelectedIndex = 0; } #endregion #region 코드로 적용 버튼 클릭시 처리하기 - applyByCodeButton_Click(sender, e) /// <summary> /// 코드로 적용 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void applyByCodeButton_Click(object sender, EventArgs e) { XPTheme xpTheme = new XPTheme(this.tChart.Chart); xpTheme.Apply(); } #endregion } } |
TestProject.zip
■ ResourceDictionary 클래스를 사용해 개별 어셈블리의 리소스 딕셔너리를 만드는 방법을 보여준다. [TestLibrary 프로젝트] ▶ BlueColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Blue" /> </ResourceDictionary> |
▶ BlueSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">0</CornerRadius> </ResourceDictionary> |
▶ BlueSkin.xaml
1 2 3 4 5 6 7 8 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="BlueColor.xaml" /> <ResourceDictionary Source="BlueSize.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> |
■ ResourceDictionary 클래스에서 느슨한 XAML 스키닝을 사용하는 방법을 보여준다. ▶ BlueColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Blue" /> </ResourceDictionary> |
▶ BlueSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">0</CornerRadius> </ResourceDictionary> |
▶ BlueSkin.xaml
1 2 3 4 5 6 7 8 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="BlueColor.xaml" /> <ResourceDictionary Source="BlueSize.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> |
▶ RedColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Red" /> </ResourceDictionary> |
▶
■ ResourceDictionary 클래스에서 컴파일 및 동적 스키닝을 사용하는 방법을 보여준다. (기능 개선) ▶ BlueColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Blue" /> </ResourceDictionary> |
▶ BlueSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">0</CornerRadius> </ResourceDictionary> |
▶ BlueSkin.xaml
1 2 3 4 5 6 7 8 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="BlueColor.xaml" /> <ResourceDictionary Source="BlueSize.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> |
▶
■ ResourceDictionary 클래스에서 컴파일 및 동적 스키닝을 사용하는 방법을 보여준다. ▶ BlueColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Blue" /> </ResourceDictionary> |
▶ BlueSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">0</CornerRadius> </ResourceDictionary> |
▶ RedColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Red" /> </ResourceDictionary> |
▶ RedSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">10</CornerRadius> </ResourceDictionary> |
■ ResourceDictionary 클래스에서 컴파일 및 정적 스키닝을 사용하는 방법을 보여준다. ▶ BlueColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Blue" /> </ResourceDictionary> |
▶ BlueSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">0</CornerRadius> </ResourceDictionary> |
▶ RedColor.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalBackgroundSolidColorBrushKey" Color="Red" /> </ResourceDictionary> |
▶ RedSize.xaml
1 2 3 4 5 6 7 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <CornerRadius x:Key="NormalCornerRadiusKey">10</CornerRadius> </ResourceDictionary> |
■ FrameworkElement 엘리먼트의 RequestedTheme 속성을 사용해 테마를 변경하는 방법을 보여준다. ▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<Page x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" FontFamily="나눔고딕코딩" FontSize="16"> <Grid Margin="100"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="50" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid Name="grid" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300" MinHeight="200" RequestedTheme="Light" BorderThickness="1" BorderBrush="DimGray" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Margin="10" Spacing="10"> <TextBlock Style="{ThemeResource SubheaderTextBlockStyle}" Text="Lorem Ipsum" /> <TextBlock TextWrapping="WrapWholeWords" Text="The background of this grid animates when the theme changes." /> <Button Content="Button" /> <CheckBox Content="CheckBox" /> </StackPanel> </Grid> <Button Grid.Column="2" VerticalAlignment="Center" Content="테마 변경" Click="changeButton_Click" /> </Grid> </Page> |
▶ MainPage.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
using Windows.Foundation; using Windows.Graphics.Display; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace TestProject { /// <summary> /// 메인 페이지 /// </summary> public sealed partial class MainPage : Page { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); #region 윈도우 크기를 설정한다. double width = 800d; double height = 600d; double dpi = (double)DisplayInformation.GetForCurrentView().LogicalDpi; ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize; Size windowSize = new Size(width * 96d / dpi, height * 96d / dpi); ApplicationView.PreferredLaunchViewSize = windowSize; Window.Current.Activate(); ApplicationView.GetForCurrentView().TryResizeView(windowSize); #endregion #region 윈도우 제목을 설정한다. ApplicationView.GetForCurrentView().Title = "FrameworkElement 엘리먼트 : RequestedTheme 속성을 사용해 테마 변경하기"; #endregion } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 테마 변경 버튼 클릭시 처리하기 - changeButton_Click(sender, e) /// <summary> /// 테마 변경 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void changeButton_Click(object sender, RoutedEventArgs e) { this.grid.RequestedTheme = (this.grid.RequestedTheme == ElementTheme.Dark) ? ElementTheme.Light : ElementTheme.Dark; } #endregion } } |
TestProject.zip
■ ThemeData 클래스의 visualDensity 속성을 사용하는 방법을 보여준다. ▶ 예제 코드 (DART)
1 2 3 4 5 6 |
ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ) |
■ Theme 클래스를 사용해 다크 테마를 설정하는 방법을 보여준다. ▶ main.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
import 'package:flutter/material.dart'; void main() { runApp(TestApplication()); } class TestApplication extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Test Application', theme: ThemeData( primarySwatch: Colors.blue, ), home: MainPage(), ); } } class MainPage extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { DateTime _selectedDate; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Test Application'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RaisedButton( child: Text('Run'), color: Colors.blue, textColor: Colors.white, onPressed: () { Future<DateTime> future = showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2018), lastDate: DateTime(2030), builder: (BuildContext context, Widget child) { return Theme( data: ThemeData.dark(), child: child, ); }, ); future.then((date) { setState(() { _selectedDate = date; }); }); }, ), Text( '결과 : $_selectedDate', ), ], ), ), ); } } |
■ ResourceDictionary 엘리먼트의 Source 속성을 사용해 특정 윈도우즈 테마를 설정하는 방법을 보여준다. ▶ MainApplication.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<Application x:Class="TestProject.MainApplication" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> <!--ResourceDictionary Source="/PresentationFramework.Classic, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/classic.xaml" /--> <!--ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" /--> <!--ResourceDictionary Source="/PresentationFramework.Luna, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/luna.metallic.xaml" /--> <!--ResourceDictionary Source="/PresentationFramework.Luna, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/luna.homestead.xaml" /--> <ResourceDictionary Source="/PresentationFramework.Royale, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/royale.normalcolor.xaml" /> </Application.Resources> </Application> |
▶ MainWindow.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<Window x:Class="TestProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="800" Height="600" Title="ResourceDictionary 엘리먼트 : Source 속성을 사용해 특정 윈도우즈 테마 설정하기" FontFamily="나눔고딕코딩" FontSize="16"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Button Width="100" Height="30" Content="Test" /> <StackPanel HorizontalAlignment="Center" Margin="0 10 0 0" Orientation="Horizontal"> <RadioButton Content="예" /> <RadioButton Margin="10 0 0 0" Content="아니오" /> </StackPanel> <ListBox Margin="0 10 0 0" Width="200" Height="100"> <TextBlock>서울</TextBlock> <TextBlock>인천</TextBlock> <TextBlock>수원</TextBlock> <TextBlock>대전</TextBlock> <TextBlock>대구</TextBlock> <TextBlock>울산</TextBlock> <TextBlock>광주</TextBlock> <TextBlock>부산</TextBlock> </ListBox> </StackPanel> </Grid> </Window> |
※ PresentationFramework.Aero 어셈블리를 참조한다.
■ 색상 테마를 설정하는 방법을 보여준다. 1. Visual Studio Code를 실행한다. 2. [File] > [Preferences] > [Color Theme] 메뉴를 클릭한다. 3. 아래
■ FrameworkElement 클래스의 DefaultStyleKeyProperty 속성을 사용해 컨트롤의 테마 스타일을 설정하는 방법을 보여준다. ▶ generic.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TestProject"> <Style x:Key="SliderRepeatButtonStyleKey" TargetType="{x:Type RepeatButton}"> <Setter Property="OverridesDefaultStyle" Value="true" /> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Focusable" Value="false" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type RepeatButton}"> <Border Background="{TemplateBinding Background}" /> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="{x:Type local:ColorThumb}" TargetType="{x:Type local:ColorThumb}"> <Setter Property="PointerOutlineBrush" Value="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" /> <Setter Property="PointerOutlineThickness" Value="2" /> <Setter Property="Foreground" Value="{x:Null}" /> <Setter Property="ThumbColor" Value="Transparent" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="Height" Value="5" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ColorThumb}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <Polygon Name="arrowPolygon" Stroke="{TemplateBinding PointerOutlineBrush}" StrokeThickness="{TemplateBinding PointerOutlineThickness}" Stretch="Fill" Points="100 20 80 50 100 80"> <Polygon.Fill> <SolidColorBrush Color="{Binding ThumbColor, RelativeSource={RelativeSource TemplatedParent}}" /> </Polygon.Fill> </Polygon> </Border> <ControlTemplate.Triggers> <Trigger Property="IsDragging" Value="False"> <Setter TargetName="arrowPolygon" Property="BitmapEffect"> <Setter.Value> <BitmapEffectGroup> <BevelBitmapEffect BevelWidth="5" Relief="0.5" /> <DropShadowBitmapEffect /> </BitmapEffectGroup> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="{x:Type local:SpectrumSlider}" TargetType="{x:Type local:SpectrumSlider}"> <Setter Property="Orientation" Value="Vertical" /> <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /> <Setter Property="Minimum" Value="0" /> <Setter Property="Maximum" Value="100" /> <Setter Property="TickFrequency" Value="0.001" /> <Setter Property="IsSnapToTickEnabled" Value="True" /> <Setter Property="IsDirectionReversed" Value="False" /> <Setter Property="Value" Value="1" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:SpectrumSlider}"> <Border Height="{TemplateBinding Height}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" MinWidth="{TemplateBinding Slider.MinWidth}" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Border x:Name="PART_TrackBackground" Grid.Column="1" Margin="10 0 10 0" Width="20"> <Rectangle x:Name="PART_SpectrumDisplay" Stretch="Fill" VerticalAlignment="Stretch" /> <Border.BitmapEffect> <BevelBitmapEffect BevelWidth="3" EdgeProfile="BulgedUp" Relief="0.3" /> </Border.BitmapEffect> </Border> <Canvas Grid.Column="1" HorizontalAlignment="Center" Width="4"> <Rectangle x:Name="PART_SelectionRange" Canvas.Left="1" Width="2.0" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Visibility="Hidden" /> </Canvas> <Track Name="PART_Track" Grid.Column="1"> <Track.DecreaseRepeatButton> <RepeatButton Style="{StaticResource SliderRepeatButtonStyleKey}" Command="Slider.DecreaseLarge" /> </Track.DecreaseRepeatButton> <Track.IncreaseRepeatButton> <RepeatButton Style="{StaticResource SliderRepeatButtonStyleKey}" Command="Slider.IncreaseLarge" /> </Track.IncreaseRepeatButton> <Track.Thumb> <local:ColorThumb x:Name="Thumb" Height="20" ThumbColor="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}}" /> </Track.Thumb> </Track> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelectionRangeEnabled" Value="true"> <Setter TargetName="PART_SelectionRange" Property="Visibility" Value="Visible" /> </Trigger> <Trigger Property="Width" Value="Auto"> <Setter Property="MinWidth" Value="21" /> </Trigger> <Trigger Property="Height" Value="Auto"> <Setter Property="MinHeight" Value="104" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> |
▶ SpectrumSlider.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
using System.Collections.Generic; using System.Windows; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Controls; namespace TestProject { /// <summary> /// 스펙트럼 슬라이더 /// </summary> public class SpectrumSlider : Slider { //////////////////////////////////////////////////////////////////////////////////////////////////// DependencyProperty ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 선택 색상 속성 - SelectedColorProperty /// <summary> /// 선택 색상 속성 /// </summary> private static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register ( "SelectedColor", typeof(Color), typeof(SpectrumSlider), new PropertyMetadata(Colors.Transparent) ); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 스펙트럼 표시명 /// </summary> private static string SPECTRUN_DISPLAY_NAME = "PART_SpectrumDisplay"; #endregion ////////////////////////////////////////////////////////////////////////////////////////// Instance //////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 스펙트럼 표시 사각형 /// </summary> private Rectangle spectrumDisplayRectangle; /// <summary> /// 색상 초기화 여부 /// </summary> private bool colorInitialized = false; /// <summary> /// 선택기 브러시 /// </summary> private LinearGradientBrush pickerBrush; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 선택 색상 - SelectedColor /// <summary> /// 선택 색상 /// </summary> public Color SelectedColor { get { return (Color)GetValue(SelectedColorProperty); } set { SetValue(SelectedColorProperty, value); } } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Static #region 생성자 - SpectrumSlider() /// <summary> /// 생성자 /// </summary> static SpectrumSlider() { DefaultStyleKeyProperty.OverrideMetadata ( typeof(SpectrumSlider), new FrameworkPropertyMetadata(typeof(SpectrumSlider)) ); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 템플리트 적용시 처리하기 - OnApplyTemplate() /// <summary> /// 템플리트 적용시 처리하기 /// </summary> public override void OnApplyTemplate() { base.OnApplyTemplate(); this.spectrumDisplayRectangle = GetTemplateChild(SPECTRUN_DISPLAY_NAME) as Rectangle; if(!this.colorInitialized) { UpdateColorSpectrum(); OnValueChanged(0, 0); } } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 값 변경시 처리하기 - OnValueChanged(previousValue, newValue) /// <summary> /// 값 변경시 처리하기 /// </summary> /// <param name="previousValue">이전 값</param> /// <param name="newValue">신규 값</param> protected override void OnValueChanged(double previousValue, double newValue) { base.OnValueChanged(previousValue, newValue); Color? color = ColorHelper.GetColor(360 - newValue, 1, 1); SetValue(SelectedColorProperty, color); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 스펙트럼 생성하기 - CreateSpectrum() /// <summary> /// 스펙트럼 생성하기 /// </summary> private void CreateSpectrum() { this.pickerBrush = new LinearGradientBrush(); this.pickerBrush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; this.pickerBrush.StartPoint = new Point(0.5, 0); this.pickerBrush.EndPoint = new Point(0.5, 1); List<Color> colorList = ColorHelper.GetHSVColorList(); double stopIncrement = (double)1 / colorList.Count; int i; for(i = 0; i < colorList.Count; i++) { this.pickerBrush.GradientStops.Add(new GradientStop(colorList[i], i * stopIncrement)); } this.pickerBrush.GradientStops[i - 1].Offset = 1.0; this.spectrumDisplayRectangle.Fill = pickerBrush; } #endregion #region 색상 스펙트럼 업데이트하기 - UpdateColorSpectrum() /// <summary> /// 색상 스펙트럼 업데이트하기 /// </summary> private void UpdateColorSpectrum() { if(this.spectrumDisplayRectangle != null) { this.colorInitialized = true; CreateSpectrum(); } else { this.colorInitialized = false; } } #endregion } } |
▶ MainWindow.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<Window x:Class="TestProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TestProject" Width="800" Height="600" Title="FrameworkElement 클래스 : DefaultStyleKeyProperty 속성을 사용해 컨트롤 테마 스타일 설정하기" FontFamily="나눔고딕코딩" FontSize="16"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <local:SpectrumSlider x:Name="slider" Width="40" Height="300" IsMoveToPointEnabled="True" IsSnapToTickEnabled="False" Maximum="360" Value="0" /> <Label HorizontalAlignment="Center" Content="{Binding ElementName=slider, Path=Value}" /> </StackPanel> </Grid> </Window> |
TestProject.zip
■ FrameworkElement 엘리먼트의 OverridesDefaultStyle 속성을 사용해 테마 스타일을 사용하는 방법을 보여준다. ▶ 예제 코드 (XAML)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<Style x:Key="RepeatButtonStyleKey" TargetType="{x:Type RepeatButton}"> <Setter Property="OverridesDefaultStyle" Value="true" /> <Setter Property="IsTabStop" Value="false" /> <Setter Property="Focusable" Value="false" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type RepeatButton}"> <Border Background="{TemplateBinding Background}" /> </ControlTemplate> </Setter.Value> </Setter> </Style> |
■ Control 클래스의 EnableTheming 속성을 사용해 테마 적용 여부를 설정하는 방법을 보여준다. ▶ Blue.skin
1 2 3 4 5 6 7 8 |
<asp:Button runat="server" BorderWidth="1px" BorderStyle="Dashed" BorderColor="Blue" BackColor="Yellow" ForeColor="Blue" /> |
▶ Blue.css
1 2 3 4 5 6 |
body { color : blue; } |
▶ MainPage.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<%@ Page Language="C#" AutoEventWireup="true" Theme="Blue" CodeBehind="MainPage.aspx.cs" Inherits="TestProject.MainPage" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Control 클래스 : EnableTheming 속성을 사용해 테마 적용 여부 설정하기</title> </head> <body> <form id="form" runat="server"> <div> 블루 스킨 적용 페이지 <hr /> <asp:Button ID="button1" runat="server" Text="블루 스킨 적용 버튼" /> <asp:Button ID="button2" runat="server" EnableTheming="false" Text="블루 스킨 미적용 버튼" /> </div> </form> </body> </html> |
▶
■ Web.config 파일을 사용해 테마를 설정하는 방법을 보여준다. ▶ Web.config
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <pages theme="Red" /> <compilation targetFramework="4.6" debug="true" /> <httpRuntime targetFramework="4.6" /> </system.web> </configuration> |
▶ Blue.skin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<asp:Button runat="server" BorderWidth="1px" BorderStyle="Dashed" BorderColor="Blue" BackColor="Yellow" ForeColor="Blue" /> <asp:Button SkinID="Bold" runat="server" BorderWidth="1px" BorderStyle="Dashed" BorderColor="Blue" BackColor="Yellow" ForeColor="Blue" Font-Bold="True" /> |
▶ Blue.css
1 2 3 4 5 6 |
body { color : blue; } |
▶ Red.skin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<asp:Button runat="server" BorderWidth="1px" BorderStyle="Dashed" BorderColor="Red" BackColor="Yellow" ForeColor="Red" /> <asp:Button SkinID="Bold" runat="server" BorderWidth="1px" BorderStyle="Dashed" BorderColor="Red" BackColor="Yellow" ForeColor="Red" Font-Bold="True" /> |
▶ Red.css