如何在app.xaml中设置默认的WPF窗口样式?
我想在我的app.xaml中的WPF Windows应用程序中的每个窗口设置默认样式。 到目前为止,我在app.xaml中有这个:
<Application.Resources> <ResourceDictionary> <Style x:Key="WindowStyle" TargetType="{x:Type Window}"> <Setter Property="Background" Value="Blue" /> </Style> </ResourceDictionary> </Application.Resources>
当运行应用程序(但不是VSdevise器)时,我可以通过特别告诉窗口使用这个样式来使窗口出现在这个样式中:
Style="{DynamicResource WindowStyle}
这工作,但不理想。 那么我如何:
- 让所有窗口自动使用样式(所以我不必在每个窗口中指定它)?
- VSdevise师有风格吗?
谢谢!
为了补充一下雷的话:
对于样式,您需要提供一个密钥/ ID或指定一个TargetType。
如果一个FrameworkElement没有明确指定的Style,它总是会寻找一个Style资源,使用它自己的types作为关键字
– 编程WPF(Sells,Griffith)
如果提供TargetType,则该types的所有实例都将应用该样式。 然而派生types不会…看起来。 <Style TargetType="{x:Type Window}">
不适用于所有的自定义派生/窗口。 <Style TargetType="{x:Type local:MyWindow}">
将仅适用于MyWindow。 所以选项是
- 使用您指定的键控样式作为您想要应用样式的每个窗口的样式属性。 devise师将展示风格的窗口。
。
<Application.Resources> <Style x:Key="MyWindowStyle"> <Setter Property="Control.Background" Value="PaleGreen"/> <Setter Property="Window.Title" Value="Styled Window"/> </Style> </Application.Resources> ... <Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}"> ...
- 或者你可以派生自定义的BaseWindow类(它有自己的怪癖 ),在Ctor / Initialization / Load阶段你可以设置Style属性一次。 所有的派生将自动具有应用的风格。 但devise师不会注意到你的风格你需要运行你的应用程序来看看正在应用的风格..我猜devise师只是运行InitializeComponent(这是自动/devise器生成的代码),所以应用XAML,但不是自定义代码隐藏。
所以我会说明确指定的样式是最less的工作。 你可以任意改变风格的方面。
知道这是几年后,但因为问题仍然在这里…
-
在您的项目中创build资源字典(右键单击项目…)
我将在名为“Assets”的Project下创build一个新文件夹,并在其中放入“resourceDict.XAML”。
-
将代码添加到resourceDict.XAML:
<Style x:Key="WindowStyle" Target Type="Window" > <Setter Property="Background" Value="Blue" /> </Style>
-
在你的Project XAML文件中,在Window下添加以下内容:
<Window.Resources> <ResourceDictionary> <!-- Believe it or not the next line fixes a bug MS acknowledges --> <Style TargetType="{x:Type Rectangle}" /> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Assets/resourceDict.XAML" /> </ResourceDictionary.MergedDictionaries> <ResourceDictionary> </Window.Resources>
引用下面的网站: 麻烦引用包含合并词典的资源词典 “有一个错误:如果所有默认样式嵌套在合并词典三层深(或更深)顶级词典不会被标记,所以search跳过它的解决方法是将一个默认的样式放在根字典中的任何东西上。 而且似乎可以可靠地解决问题。 去搞清楚…
-
最后,在窗口下,也许在标题之后,但在最后一个窗口“>”之前:
Style="{DynamicResource windowStyle}"
-
而且您需要将步骤3和4中的代码添加到要应用样式的每个项目中。
-
如果您想要使用渐变背景而不是纯色,请将以下代码添加到resourceDict.XAML中:
<LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0" EndPoint="0,1" > <GradientStop Color= "AliceBlue" Offset="0" /> <GradientStop Color= "Blue" Offset=".75" /> </LinearGradientBrush>
-
并修改您的风格设置器的背景颜色阅读:
<Setter Property="Background" Value="{DynamicResource windowGradientBackground}" />
步骤3和4需要在每个project.XAML文件中重复,如上所述,但是,嘿,你可以在解决scheme中获得统一的Windows! 同样的过程也适用于你想要有统一外观的任何控件,button等等。
对于任何人进入这一晚,希望这有助于我确信原来的海报几年前得出这一切。
保罗
devise师不工作,因为你指定一个DynamicResource。 请把它改成StaticResource,一切都会好的。
要应用于所有窗口,您应该从样式中移除x:Key。 设置TargetType隐式地将x:Key设置为TargetType中的任何值。 但是,在我的testing中,这是行不通的,所以我正在研究它。
如果我将TargetType设置为x:Type TextBlock,则devise器完美地工作,它似乎是显示不同行为的Window。
我调查了这一天,现在通过我的自定义窗口类的构造函数工作:
public class KWindow : Window { public KWindow() { this.SetResourceReference(StyleProperty, typeof(KWindow)); } static KWindow() { DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); // gets called finally } }
希望它可以帮助别人
对于那些为解决这个问题而挣扎的人们:我怎样才能将自定义样式自动应用到所有的Window派生types? 下面是我想出的解决scheme
注意:我真的不想从窗口types派生或必须在每个窗口插入XAML强制风格更新等特定于我的项目的原因(我的产品消费者我通用的可重用的样式库,并创build自己的布局/窗口等),所以我真的有动力去找出一个解决办法,我愿意忍受任何副作用
需要遍历所有实例化的窗口,并强制它们使用您为Windowtypes定义的新自定义样式。 这适用于已经启动的窗口,但是当窗口或子窗口被实例化时,它不知道使用已经为其基types声明的新/自定义types; 香草窗口types。 所以最好的办法是在MainWindow上使用LostKeyBoardFocus,当它失去焦点到ChildWindow(IOW当一个子窗口被创build),然后调用这个FixupWindowDerivedTypes()。
如果有人有更好的解决scheme来检测任何种类的窗口派生types实例化,因此调用FixupWindowDerivedTypes()将是伟大的。 在这个区域中处理WM_WINDOWPOSCHANGING也可能有用。
所以这个解决scheme并不优雅,但是不需要我去触摸与我的窗口相关的任何代码或XAML就能完成工作。
public static void FixupWindowDerivedTypes() { foreach (Window window in Application.Current.Windows) { //May look strange but kindly inform each of your window derived types to actually use the default style for the window type window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window)); } } } } //Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection. http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html //Helper class to retrieve a protected property so we can set it internal class DefaultStyleKeyRetriever : Control { /// <summary> /// This method retrieves the default style key of a control. /// </summary> /// <param name="control">The control to retrieve the default style key /// from.</param> /// <returns>The default style key of the control.</returns> public static object GetDefaultStyleKey(Control control) { return control.GetValue(Control.DefaultStyleKeyProperty); } }
您可以将此代码添加到您的App.xaml.cs文件中:
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata { DefaultValue = Application.Current.FindResource(typeof(Window)) });
在此之后,应用于Window
types的样式也适用于从Window
派生的所有types
考虑到Gishu的回答,我想出了一个解决方法。 但可能有点怪异。 如果使用MVVM模式,则可以删除窗口的代码隐藏,并在XAML文件中删除x:Class标记。 所以你将得到一个窗口或你的自定义窗口的实例,但不是从“窗口”类派生并标记为部分的“MainWindow”类的某个实例。 我做类似VS的窗口,所以我不得不inheritance窗口类,并扩展它的function。 在这种情况下,可以将新的窗口类作为部分,这将允许我们在没有inheritance的情况下进行代码隐藏。
-
你将所有的样式保存在一个xaml文件中(例如:design.xaml)
-
然后像这样调用所有页面中的(design.xaml)xaml文件
喜欢:
<ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Design.xaml"/> </ResourceDictionary.MergedDictionaries>