简体   繁体   中英

Change wpf style while program running

This is what i put in my app.xaml which I use this style in many places at my code:

<Style x:Key="windowStyleDefault">
    <Setter Property="Control.Background" Value="#F0F0F0" />
    <Setter Property="Control.Foreground" Value="#179DD1" />
</Style>

I want to change the whole application fonts and colors (let's start with color):

<Menu  Style="{DynamicResource windowStyleDefault}" >
    <MenuItem Header="File" >
        <MenuItem x:Name="NewFarmReport" Header="New Farm Report" Click="NewFarmReport_Click"/>
        <Separator/>
        <MenuItem x:Name="Exit" Header="Exit" Click="Exit_Click"/>
    </MenuItem>
    <MenuItem Header="Settings">
        <MenuItem x:Name="GuiSettings" Header="GUI Settings" Click="GuiSettings_Click"/>
        <MenuItem x:Name="CurrentWeightSettings" Header="Current Weights Settings" Click="CurrentWeightSettings_Click"/>
        <MenuItem x:Name="DefaultWeightSettings" Header="Default Weights Settings" Click="DefaultWeightSettings_Click"/>
    </MenuItem>
    <MenuItem Header="View">
        <MenuItem Header="Show History" x:Name="ShowHistory" Click="ShowHistory_Click"/>
    </MenuItem>
    <MenuItem Header="Compare" x:Name="CompateBtn" Click="CompateBtn_Click">
    </MenuItem>
</Menu>

at this code, I declare a menu using this windowStyleDefault :

<Grid DockPanel.Dock="Top" Style="{StaticResource windowStyleDefault}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="6*"/>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>    
    <Label FontStretch="Normal" FontWeight="Bold" FontSize="17" DockPanel.Dock="Top" Content="Report History" Style="{StaticResource windowStyleDefault }" Margin="0,0,2,2" />    
    <Image x:Name="OpenSlectionMode" Margin="0,0,6,-0.4" MouseEnter="OpenSlectionMode_MouseEnter" MouseLeave="OpenSlectionMode_MouseLeave"
                           MouseLeftButtonDown="OpenSlectionMode_MouseLeftButtonDown" MaxWidth="30" MaxHeight="30" Grid.ColumnSpan="2" HorizontalAlignment="Right" Width="16"
                           Source="{StaticResource selection}"/>    
    <Image x:Name="ClosdeHistoryImage" Margin="0,0,6,-0.4" MouseLeftButtonDown="CloseHistoryImage_MouseLeftButtonDown" 
                           MouseEnter="CloseHistoryImage_MouseEnter" MouseLeave="CloseHistoryImage_MouseLeave"
                           MaxWidth="20" MaxHeight="20" Grid.ColumnSpan="3" HorizontalAlignment="Right" Width="16"
                           Source="{StaticResource CloseHistoryNormal}"/>    
</Grid>

and here I use for DockPanel .

You seem to have part of it covered there.
If you use dynamicresource:

<Menu  Style="{DynamicResource windowStyleDefault}" >

Then it will pick up a change in windowStyleDefault. It must be the whole thing being replaced.
You can do that in at least two ways.
You can merge in another resource dictionary into application.current.resources OR a control's resources at a scope containing wherever you want the change to apply. If that resource dictionary has an entry with the same key and different stuff then it'll change.
Or you can do it in code.

Go get a style from wherever you like and then set it:

Application.Current.Resources["windowStyleDefault"] = yourNewStyle;

If you instead used staticresource then that won't pick up changes.

Whether any of these are what you'd call suitable, I can only guess.

There is one approach that I know of, its ResourceDictionary , very easy and useful in many cases such as making your app multilingual or adding themes..

First of all, for every theme you want to add, you should add a ResourceDictionary to your project and define the styles or fonts or brushes or whatever resources you want to use as theme, in that particular ResourceDictionary.

Example (MyFirstTheme.xaml):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <FontFamily x:Key="MyFont">Segoe UI</FontFamily>
    <SolidColorBrush x:Key="MyThemeColor" Color="#FF34495E"/>

</ResourceDictionary>

Example (MySecondTheme.xaml):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <FontFamily x:Key="MyFont">Tahoma</FontFamily>
    <SolidColorBrush x:Key="MyThemeColor" Color="#D89A9E"/>

</ResourceDictionary>

You should add resource dictionaries as many themes you have. And for setting one as default, you should address it in your App.xaml file like this:

<Application x:Class="MyApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="Themes\MyFirstTheme.xaml"/> 
                // This will be the default theme

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

For assigning theme on objects or controls, you should do as following:

<Window x:Name="window" x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        Title="MyApp" Height="400" Width="400"  FontFamily="{DynamicResource MyFont}">

        <Grid>
                <TextBlock Foreground="{DynamicResource MyThemeColor}" Text="Theme Test" />
        </Grid>
</Window>

Note: When you are using resources on your controls or objects, the binding must be defined as DynamicResource

Let's assume that you've added your all theme dictionaries and you want to switch between them in code behind, use this function:

public void ChangeTheme(string ThemeName)
{
     ResourceDictionary dict = new ResourceDictionary();
                dict.Source = new Uri("..\\Themes\\" + ThemeName + ".xaml", UriKind.Relative);
                App.Current.Resources.MergedDictionaries.Add(dict);
}

Usage:

 ChangeTheme("MySecondTheme");
 UpdateLayout();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM