dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.04k stars 1.16k forks source link

Application styles are only applied if there is more than one style when StartupUri is not used #4457

Open jnm2 opened 3 years ago

jnm2 commented 3 years ago

The application style has no effect, but it should have an effect. The style starts taking effect as soon as a second unrelated style is added before or after it.

This causes a long search for ways to fix the problem and is not beginner-friendly.

image

Full repro created from VS template

Download: Repro.zip

<Application x:Class="WpfRepro.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <Style TargetType="TextBox">
            <Setter Property="Background" Value="Red"/>
        </Style>
        <!-- Uncomment to see the style above start taking effect -->
        <!-- <Style x:Key="Workaround" /> -->
    </Application.Resources>
</Application>
<Window x:Class="WpfRepro.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"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfRepro"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <TextBox />
</Window>
using System.Windows;

namespace WpfRepro
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            new MainWindow(startupUriIsNotAnOption: 42).Show();
        }
    }
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>
daisyTian0517 commented 3 years ago

You need to add a ResourceDictionary to contain your Style and make it to the Application.Current.Resources.Source in App.xaml.cs, eg, You can put your style into a ResourceDictionary named a Dictionary1 , and add below code to your App.xaml.cs

 public App()
        {
            Application.Current.Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri("/ApplicationStyles;Component/Dictionary1.xaml",UriKind.Relative)) as ResourceDictionary);
        }
jnm2 commented 3 years ago

Why is this needed if it's not needed when StartupUri is used and it's not needed if there is more than one style?

ThomasGoulet73 commented 3 years ago

This bug looks really weird. It's from the code generated by PresentationBuildTasks.dll.

See the difference between the generated code in App.g.i.cs:

Without