프로그램 개발/C#

[wpf] c# 코드로 Style 설정하기 - 2 : 다른 Resource Dictionary 사용

(ㅇㅅㅎ) 2021. 3. 2. 23:54
728x90
반응형

다른 Resource Dictionary 안에 존재하는 다른 Stsyle을 c# 코드로 변경하는 방법입니다.

string resourcePath = "/프로젝트이름;component/ResourceDictionary위치.xaml";
ResourceDictionary res = (ResourceDictionary)Application.LoadComponent(new Uri(resourcePath, UriKind.Relative));

Control.Style = (Style)res["ResourceKey"];

 

예제를 따라 하시려면 더보기를 클릭하세요.

더보기

Grid 안에 Label과 Button을 한 개씩 준비합니다. 

xaml
    <Grid x:Name="G1">
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Label Name="L1"/>
            <Button x:Name="B1" Click="Button_Click"/>
        </StackPanel>
    </Grid>

 

2가지 Resource Dictionary를 준비합니다.

ResourceDictionary : LightMode.xaml
    <Style TargetType="Grid" x:Key="GridStyle">
        <Setter Property="Background" Value="GhostWhite"/>
    </Style>
    
    <Style TargetType="Label" x:Key="LabelStyle">
        <Setter Property="Content" Value="라이트 모드"/>
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="Black"/>
    </Style>

    <Style TargetType="Button" x:Key="ButtonStyle">
        <Setter Property="Width" Value="50"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="Content" Value="변경"/>
        <Setter Property="BorderBrush" Value="Black"/>
        <Setter Property="Background" Value="WhiteSmoke"/>
    </Style>

 

ResourceDictionary : DarkMode.xaml
    <Style TargetType="Grid" x:Key="GridStyle">
        <Setter Property="Background" Value="Black"/>
    </Style>

    <Style TargetType="Label" x:Key="LabelStyle">
        <Setter Property="Content" Value="다크 모드"/>
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="FontWeight" Value="ExtraBold"/>
        <Setter Property="Foreground" Value="White"/>
    </Style>

    <Style TargetType="Button" x:Key="ButtonStyle">
        <Setter Property="Width" Value="50"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="Content" Value="변경"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="BorderBrush" Value="White"/>
        <Setter Property="Background" Value="Black"/>
    </Style>

 

c#
using System;
using System.Windows;
using System.Windows.Controls;
 
namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        ResourceDictionary lightmode = (ResourceDictionary)Application.LoadComponent(new Uri("/WpfApp1;component/LightMode.xaml", UriKind.Relative));
        ResourceDictionary darkmode = (ResourceDictionary)Application.LoadComponent(new Uri("/WpfApp1;component/DarkMode.xaml", UriKind.Relative));
 
        Style l1, g1, b1;
        Style l2, g2, b2;
 
        private bool tmp = true;
        public MainWindow()
        {
            InitializeComponent();
 
            // 라이트 모드 스타일 정의
            l1 = (Style)lightmode["LabelStyle"];
            g1 = (Style)lightmode["GridStyle"];
            b1 = (Style)lightmode["ButtonStyle"];
 
            // 다크 모드 스타일 정의
            l2 = (Style)darkmode["LabelStyle"];
            g2 = (Style)darkmode["GridStyle"];
            b2 = (Style)darkmode["ButtonStyle"];
 
            // 라이트 모드 스타일 입히기
            G1.Style = g1;
            L1.Style = l1;
            B1.Style  = b1;
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 라이트 모드일 때
            if (tmp)
            {
                tmp = false;
 
                // 다크 모드 스타일 입히기
                G1.Style = g2;
                L1.Style = l2;
                B1.Style = b2;
            }
            // 다크 모드일 때
            else
            {
                tmp = true;
 
                // 라이트 모드 스타일 입히기
                G1.Style = g1;
                L1.Style = l1;
                B1.Style = b1;
            }
        }
    }
}
 
 

 


위와 같은 방법은 컴포넌트 1개의 스타일을 바꿀 때는 유용하지만 라이트 모드/다크 모드처럼 모든 것을 변경할 때는 귀찮습니다. 이럴 때 아래와 같이 사용하는 것이 편리합니다.


App.xaml
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary x:Name="ThemeDictionary">
                    <ResourceDictionary.MergedDictionaries>
                        <ResourceDictionary Source="/WpfApp1;component/LightMode.xaml"/>
                    </ResourceDictionary.MergedDictionaries>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

 

App.xaml.cs
using System;
using System.Windows;
 
namespace WpfApp1
{
    /// <summary>
    /// App.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class App : Application
    {
        public ResourceDictionary ThemeDictionary
        {
            get { return Resources.MergedDictionaries[0]; }
        }
        public void ChangeTheme(Uri uri)
        {
            ThemeDictionary.MergedDictionaries.Clear();
            ThemeDictionary.MergedDictionaries.Add(new ResourceDictionary() { Source = uri });
        }
    }
}
 
 

 

xml
    <Grid x:Name="G1" Style="{DynamicResource GridStyle}">
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Label Name="L1" Style="{DynamicResource LabelStyle}"/>
            <Button x:Name="B1" Style="{DynamicResource ButtonStyle}" Click="Button_Click"/>
        </StackPanel>
    </Grid>

 

c#
using System;
using System.Windows;
 
namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        string lightmode_path = "/WpfApp1;component/LightMode.xaml";
        string darkmode_path = "/WpfApp1;component/DarkMode.xaml";
        
        private bool tmp = true;
        public MainWindow()
        {
            InitializeComponent();
 
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var app = (App)Application.Current;
 
            // 라이트 모드일 때
            if (tmp)
            {
                tmp = false;
 
                // 다크 모드 스타일 입히기
                app.ChangeTheme(new Uri(darkmode_path, UriKind.Relative));
            }
            // 다크 모드일 때
            else
            {
                tmp = true;
 
                // 라이트 모드 스타일 입히기
                app.ChangeTheme(new Uri(lightmode_path, UriKind.Relative));
            }
        }
    }
}
 
 

 

참고 자료

stackoverflow.com/questions/33867091/how-to-change-resourcedictionary-dynamically

 

How to change ResourceDictionary Dynamically

I need to change ResourceDictionary in App.xaml file dynamically. I have tried the following code: ResourceDictionary newRes = new ResourceDictionary(); newRes.Source = new Uri("/PsyboInventory;

stackoverflow.com

 

 

반응형