我正在尝试为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>
通过专门告诉窗口通过以下方式使用此样式,我可以在运行应用程序时让窗口显示此样式(但不是VS设计器):
Style="{DynamicResource WindowStyle}
这有效,但并不理想。那么我该怎么做:
谢谢!
答案 0 :(得分:45)
添加Ray所说的内容:
对于样式,您需要提供Key / ID或指定TargetType。
如果FrameworkElement没有 明确指定Style,它会 总是寻找Style资源, 使用自己的类型作为关键词 - 编程WPF(Sells,Griffith)
如果提供TargetType,则该类型的所有实例都将应用样式。然而,衍生类型不会......似乎。 <Style TargetType="{x:Type Window}">
不适用于所有自定义派生/窗口。 <Style TargetType="{x:Type local:MyWindow}">
仅适用于MyWindow。所以选项是
<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}"> ...
所以我说明确指定的样式是最不起作用的。你可以集中改变风格的各个方面。
答案 1 :(得分:20)
知道这是多年以后,但因为这个问题还在这里......
在项目中创建资源字典(右键单击项目...)
我将在项目下创建一个名为“Assets”的新文件夹 将“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>
参考以下网站:Trouble referencing a Resource Dictionary that contains a Merged Dictionary “有一个错误:如果所有默认样式都嵌套在三个级别深度(或更深)的合并字典中,则顶级字典不会被标记,因此搜索会跳过它。解决方法是将默认样式放到某个东西,任何东西,在根词典中。“ 它似乎可靠地解决了问题。去图......
最后,在Window下,也许在Title之后,但在最后一个Window'&gt;'之前:
Style="{DynamicResource windowStyle}"
您需要在第3步和第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&amp; 4需要在每个project.XAML文件中重复如上所述,但是,嘿,你在整个解决方案中获得统一的Windows!并且相同的过程可以应用于您想要具有统一外观的任何控件,按钮等等。
对于那些迟到的人来说,希望这会有所帮助,因为我确信最初的海报在几年前就已经解决了。
保
答案 2 :(得分:8)
设计器无法正常工作,因为您正在指定DynamicResource。请将此更改为StaticResource,一切都会好的。
要应用于所有窗口,您应该从样式中删除x:Key。设置TargetType隐式地将x:Key设置为TargetType中的任何内容。但是,在我的测试中,这不起作用,所以我正在研究它。
如果我将TargetType设置为x:Type TextBlock,设计师工作得很好,它似乎就是显示不同行为的Window。
答案 3 :(得分:3)
我现在对这个问题进行了几天调查,并通过我的自定义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
}
}
希望它有助于某人
答案 4 :(得分:3)
您可以将此代码添加到App.xaml.cs文件中:
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
{
DefaultValue = Application.Current.FindResource(typeof(Window))
});
在此之后,应用于Window
类型的样式也将适用于从Window
答案 5 :(得分:1)
对于那些努力解决问题的人:如何将自定义样式自动应用于我的所有Window派生类型?以下是我提出的解决方案
注意:我真的不想从Window类型派生,或者必须在每个窗口上插入XAML以强制样式更新等,这是因为我的项目特定的原因(我的产品的消费者是我的通用可重用样式库和创建他们自己的布局/窗口等)所以我真的积极找出一个解决方案,我愿意和任何副作用一起生活
需要遍历所有实例化的窗口,只需强制它们使用您为Window类型定义的新自定义样式。这适用于已经启动的窗口,但是当实例化窗口或子窗口时,它将不知道使用已为其基本类型声明的新/自定义类型;香草窗口类型。因此,我能想到的最好的方法是在MainWindow上使用LostKeyBoardFocus,当它失去Focus到ChildWindow时(IOW当创建子窗口时),然后调用此FixupWindowDerivedTypes()。
如果有人在实例化任何类型的窗口派生类型时有一个更好的“检测”解决方案,那么调用FixupWindowDerivedTypes()就会很棒。在此区域中处理WM_WINDOWPOSCHANGING可能会有用。
所以这个解决方案不是很优雅,但是我可以完成工作,而不必触及与我的窗口相关的任何代码或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);
}
}
答案 6 :(得分:0)
考虑到 Gishu 的回答,我想出了另外一个解决方法。但它可能有点奇怪。 如果使用MVVM模式,则可以删除窗口的代码隐藏和XAML文件中的x:Class标记。因此,您将获得一个窗口或自定义窗口的实例,但不会获得从'Window'类派生并标记为partial的'MainWindow'类的某个实例。 我正在制作类似于VS的窗口,所以我必须继承窗口类并扩展它的功能。在这种情况下,可以将新的窗口类作为部分,以允许我们在没有继承的情况下进行代码隐藏。
答案 7 :(得分:-2)
您将所有样式保存在一个xaml文件中(例如design.xaml)
然后像这样在所有页面中调用(design.xaml)xaml文件
喜欢:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Design.xaml"/>
</ResourceDictionary.MergedDictionaries>