wpf DataTemplate 中的静态资源引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22245752/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:08:48  来源:igfitidea点击:

StaticResource reference inside DataTemplate

wpfxamldatatemplatestaticresource

提问by Theodore Zographos

I've been experiencing some strange behaviour when referencing StaticResources from inside a DataTemplate defined in a ResourceDictionary.

从 ResourceDictionary 中定义的 DataTemplate 内部引用 StaticResources 时,我遇到了一些奇怪的行为。

In this example, I fill a listbox with the numbers 1 to 9, using a DataTemplate defined in a ResourceDictionary.

在此示例中,我使用 ResourceDictionary 中定义的 DataTemplate 用数字 1 到 9 填充列表框。

Here's the MainWindow.xaml code:

这是 MainWindow.xaml 代码:

<Window x:Class="testResources.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
    Width="525"
    Height="350">
<Grid>
    <ListBox Width="100" ItemTemplate="{StaticResource NumberTemplate}">
        <ListBox.ItemsSource>
            <Int32Collection>1,2,3,4,5,6,7,8,9</Int32Collection>
        </ListBox.ItemsSource>
    </ListBox>
</Grid>

The NumberTemplateis defined in ResourceDictionary1.xaml:

NumberTemplate是在ResourceDictionary1.xaml定义:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="NumberTemplate">
    <Grid Background="{StaticResource CoolNumbersColor}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="35" />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" Background="{StaticResource CoolNumbersColor}" Text="{Binding Mode=OneWay}" />
    </Grid>
</DataTemplate>

The StaticResource CoolNumbersColoris defined in App.xaml along with ResourceDictionary1.xaml. Here's my App.xaml file:

StaticResourceCoolNumbersColor在 App.xaml 中与ResourceDictionary1.xaml. 这是我的 App.xaml 文件:

<Application x:Class="testResources.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>
        <SolidColorBrush x:Key="CoolNumbersColor">GreenYellow</SolidColorBrush>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/ResourceDictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

First of all I can see the expected behaviour in Visual Studio 2010 designer. Indeed a colored list of numbers appears. But when trying to run this sample I receive the error

首先,我可以在 Visual Studio 2010 设计器中看到预期的行为。确实会出现一个彩色数字列表。但是在尝试运行此示例时,我收到错误

"Cannot find resource named 'CoolNumbersColor'. Resource names are case sensitive"

“找不到名为‘CoolNumbersColor’的资源。资源名称区分大小写”

I can't understand why this happens. Is CoolNumbersColorevaluation deferred somehow? Lexically, it is in front of the merged resourcedictionary.

我不明白为什么会这样。CoolNumbersColor评估是否以某种方式推迟?从词法上讲,它位于合并的资源字典之前。

The only way to make this work (other than using DynamicResources) is to create a second ResourceDictionary (e.g. ResourceDictionary2.xaml), define CoolNumbersColorthere and merge them all in ResourceDictionary.MergedDictionarieslike this:

使这项工作(使用 DynamicResources 除外)的唯一方法是创建第二个 ResourceDictionary(例如 ResourceDictionary2.xaml),CoolNumbersColor在那里定义并将它们全部合并,ResourceDictionary.MergedDictionaries如下所示:

<Application x:Class="testResources.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="pack://application:,,,/ResourceDictionary2.xaml" />
            <ResourceDictionary Source="pack://application:,,,/ResourceDictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

回答by Anatoliy Nikolaev

I guess this is due to the fact that a:

我想这是由于以下事实:

StaticResource

StaticResource

  • Does not support forward references
  • It is set only once when the program starts: load-timelookup of resources
  • 不支持前向引用
  • 程序启动时只设置一次:load-timelookup of resources

DynamicResource

DynamicResource

  • Supports forward references
  • Applies for each access to the resource: run-timelookup
  • 支持前向引用
  • 适用于对资源的每次访问:运行时查找

Example of forward reference

Example of forward reference

Not work with StaticResource:

不适用于StaticResource

<Window x:Class="SeveralResourceDictionariesHelp.MainWindow"
        Background="{StaticResource testColor}" ... >

<Window.Resources>
    <SolidColorBrush x:Key="testColor">Red</SolidColorBrush>
</Window.Resources>

Work with DynamicResource:

DynamicResource

<Window x:Class="SeveralResourceDictionariesHelp.MainWindow"
        Background="{DynamicResource testColor}" ... >

<Window.Resources>
    <SolidColorBrush x:Key="testColor">Red</SolidColorBrush>
</Window.Resources>

At the time the application is launched, the CoolNumbersColor(StaticResource) not available within the "visibility" of DataTemplate, respectively, it throws an exception, he tries to find it in its scope but can not find it.

在应用程序启动时,CoolNumbersColor(StaticResource) 在 的“可见性”内不可用DataTemplate,分别抛出异常,他试图在其范围内找到它但找不到它。

When using resource dictionaries they are loaded into the first queue, respectively, in this case would be a single scope of view in which the resource is present.

当使用资源字典时,它们分别被加载到第一个队列中,在这种情况下将是资源所在的单个视图范围。

DynamicResourcewill not be loaded when the application is launched, it will be loaded during his first request to him and at this stage DataTemplateit "sees" the resource.

DynamicResource不会在应用程序启动时加载,它将在他第一次向他发出请求时加载,并且在这个阶段DataTemplate它“看到”了资源。

The question remains: Why this trick works in the Studio?. Perhaps there is a difference between loading at runtime and in design mode, but I have not found an official confirmation in the documentation or elsewhere.

问题依旧:Why this trick works in the Studio?。也许在运行时加载和在设计模式下加载之间存在差异,但我没有在文档或其他地方找到官方确认。