wpf 覆盖 XAML 中的资源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15243747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Override resource in XAML
提问by Stalker
I have following UserControl:
我有以下几点UserControl:
<UserControl x:Class="MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<SolidColorBrush x:Key="ColorKey" Color="Orange"/>
</UserControl.Resources>
<Grid Background="{StaticResource ColorKey}">
</Grid>
</UserControl>
and I use it like this:
我像这样使用它:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OverrideResource"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="OtherColorKey" Color="Blue"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<local:MyControl Grid.Row="0">
<local:MyControl.Resources>
<SolidColorBrush x:Key="ColorKey" Color="Red"/>
</local:MyControl.Resources>
</local:MyControl>
<Grid Grid.Row="1">
<Grid.Resources>
<SolidColorBrush x:Key="OtherColorKey" Color="Green"/>
</Grid.Resources>
<Grid Background="{StaticResource OtherColorKey}"/>
</Grid>
</Grid>
</Window>
Overriding of resource OtherColorKeyworks like I expect; the grid has green Background. But I would like to override a Resourcethat is used inside the UserControl(ColorKeyin my example). But I'm getting exception:
OtherColorKey像我期望的那样覆盖资源;网格有绿色Background。但我想重写一个Resource是内部使用UserControl(ColorKey在我的例子)。但我得到了例外:
Item has already been added. Key in dictionary: 'ColorKey' Key being added: 'ColorKey'
已添加项目。字典中的键:'ColorKey' 正在添加的键:'ColorKey'
This is just a simplified example, in reality I need it for a bit more complex task. I know that for examle DevExpress uses similar mechanism for customizing their controls (however they use not strings as keys, but objects derived from ResourceKey). But I'm unable to find simple working example to implement such thing on my own.
这只是一个简化的例子,实际上我需要它来完成更复杂的任务。我知道,例如 DevExpress 使用类似的机制来自定义他们的控件(但是他们不使用字符串作为键,而是使用派生自 的对象ResourceKey)。但是我无法找到简单的工作示例来自己实现这样的事情。
Thanks for your help.
谢谢你的帮助。
回答by trippedOverXaml
After reading your post, and reply to the first answer it seems you are writing an application that will require you to keep track of several styling elements. The best way to keep them organized and easily maintainable is to use a ResourceDictionary and reference it.
阅读您的帖子并回复第一个答案后,您似乎正在编写一个需要跟踪多个样式元素的应用程序。使它们井井有条且易于维护的最佳方法是使用 ResourceDictionary 并引用它。
For me, I have a much easier time when I separate mine based on what they are defining, one for the Brushes and Colors and one for the ControlTemplates and Styles (if the project is extremely complicated, then it depends on several other factors - this is just for a relatively straightforward project).
对我来说,当我根据他们定义的内容将我的内容分开时,我会轻松得多,一个用于画笔和颜色,另一个用于 ControlTemplates 和样式(如果项目非常复杂,那么它取决于其他几个因素 - 这仅适用于相对简单的项目)。
Once these ResourceDictionary files have been defined, you would reference them in the App.xaml file so they can be applied throughout the application without having to always redefine a Brush or Template in the actual XAML of the page.
一旦定义了这些 ResourceDictionary 文件,您将在 App.xaml 文件中引用它们,以便它们可以在整个应用程序中应用,而不必总是在页面的实际 XAML 中重新定义画笔或模板。
So, an example of how the App.xaml may look:
因此,App.xaml 的外观示例如下:
<Application
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"
mc:Ignorable="d"
x:Class="MyColorBlock.App"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/BrushesAndColors.xaml"/>
<ResourceDictionary Source="Resources/StylesAndTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
As stated, this is a very simplified example, so the source files are located in the same project the App.xaml is - just in the Resources folder. The BrushesAndColors.xaml is referenced before the StylesAndTemplates.xaml since the styles and templates defined depend on the colors you have defined.
如前所述,这是一个非常简化的示例,因此源文件位于 App.xaml 所在的同一项目中 - 就在 Resources 文件夹中。BrushesAndColors.xaml 在 StylesAndTemplates.xaml 之前被引用,因为定义的样式和模板取决于您定义的颜色。
For the ResourceDictionary BrushesAndColors.xaml:
对于 ResourceDictionary BrushesAndColors.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OverrideResource">
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
<SolidColorBrush x:Key="RedBrush" Color="Red"/>
<SolidColorBrush x:Key="GreenBrush" Color="Green"/>
</ResourceDictionary>
The Brushes are the same as you defined, however they can now just be referenced by their Key throughout your application.
画笔与您定义的相同,但是现在可以在整个应用程序中通过它们的键来引用它们。
For the StylesAndTemplates.xaml:
对于 StylesAndTemplates.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OverrideResource">
<!-- Adding the MergedDictionaries in this ResourceDictionary allows the control templates and styles to reference the colors and brushes defined in BrushesAndColors.xaml. Note: It is a relative link, both files in this example in the same folder "Resources" -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="BrushesAndColors.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:key="MyControlStyle" TargetType="{x:Type local:MyControl}">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource RedBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<!-- by giving the border background the value of {TemplateBinding Background} it is now set based on what the style's property has been defined as -->
<Border Background="{TemplateBinding Background}">
<TextBlock Text="Red Block Text"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- since the style is based on a predefined one it inherits that particular style's definition.
However, the background color of this stylehas been redefined, and will use that background color
on any control it is applied to instead-->
<Style x:Key="MyControlStyleTwo" TargetType="{x:Type local:MyControl}" BasedOn="{StaticResource MyControlStyle}">
<Setter Property="Background" Value="{StaticResource BlueBrush}"/>
</Style>
</ResourceDictionary>
Out of habit, I still reference the ResourceDictionary that this one needs to make sure that the styles and templates defined can find the resources I reference when creating them.
出于习惯,我还是引用了这个需要的ResourceDictionary,以确保定义的样式和模板在创建时可以找到我引用的资源。
The second style, I based it off of the first so I don't have to rewrite the entire thing - but I can simply change the color of it's background. So it will look like the first except with a different background color.
第二种风格,我基于第一种风格,所以我不必重写整个东西 - 但我可以简单地改变它的背景颜色。所以它看起来像第一个,除了背景颜色不同。
For the main window - which will change slightly:
对于主窗口 - 会略有变化:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OverrideResource"
Title="MainWindow" Height="350" Width="525">
<Grid Background="{StaticResource BlueBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<local:MyControl Style="{StaticResource MyControlStyle}" Grid.Row="0" />
<local:MyControl Style="{StaticResource MyControlStyleTwo}" Grid.Row="1"/>
</Grid>
</Window>
You no longer have to redefine any information pertaining to the UI of the application, keeping the XAML cleaner and easier to read.
您不再需要重新定义与应用程序 UI 相关的任何信息,从而使 XAML 更清晰、更易于阅读。
It may not be the "easy fix" - but it will definitely make things much easier as you continue. It will also help anyone else if more than one person is working on the project. With everything defined in a centralized area, you can keep styles and colors consistent and no one is having to sift through different pages to find what style was used, they just reference the appropriate one.
这可能不是“简单的解决方法”——但随着你的继续,它肯定会让事情变得更容易。如果不止一个人参与该项目,它也将帮助其他任何人。通过在一个集中区域中定义所有内容,您可以保持样式和颜色一致,并且没有人必须筛选不同的页面才能找到使用的样式,他们只需引用适当的样式即可。
This also allows for your control to be written only once, but by giving it different styles/templates you are able to change how the information is displayed - helping to keep the data and the display information separated :)
这也允许您的控件只编写一次,但通过为其提供不同的样式/模板,您可以更改信息的显示方式 - 有助于将数据和显示信息分开:)
Hope this helps, sorry for the long post, but it was the only way I could think of to explain how I think you could best solve your problem (and keep it solved).
希望这会有所帮助,对于这篇长文章很抱歉,但这是我能想到的唯一方法来解释我认为您如何最好地解决您的问题(并保持解决)。
回答by mdm20
OtherColorKey is being added to 2 different dictionaries (window and grid). ColorKey is being added to the same dictionary (MyControl).
OtherColorKey 被添加到 2 个不同的词典(窗口和网格)。ColorKey 被添加到同一个字典 (MyControl)。
A better way to approach this would to declare a DependencyProperty of type Brush within MyControl and set it like:
解决此问题的更好方法是在 MyControl 中声明 Brush 类型的 DependencyProperty 并将其设置为:
<local:MyControl Grid.Row="0" MyBrush="Red" />
Within MyControl, just bind whatever you want to that MyBrush property.
在 MyControl 中,只需将您想要的任何内容绑定到该 MyBrush 属性即可。
<UserControl x:Class="MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" x:Name=Me>
<Grid Background="{Binding MyBrush, ElementName=Me}">
</Grid>
</UserControl>

