【问题标题】:StaticResource reference inside DataTemplateDataTemplate 中的静态资源引用
【发布时间】:2014-04-10 08:15:43
【问题描述】:

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

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

这是 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>

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>

StaticResource CoolNumbersColorResourceDictionary1.xaml 一起在 App.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>

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

"找不到名为 'CoolNumbersColor' 的资源。资源名称为 区分大小写”

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

完成这项工作的唯一方法(使用 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>

【问题讨论】:

  • 你在哪里使用这个资源?我在小应用程序中尝试过,最终效果很好。
  • 您是否尝试在 Application.Resources 中的 ResourceDictionary.MergedDictionaries 之前定义 CoolNumbersColor ?
  • 是的,我在 DataTemplateListBox 中使用了它。仍然没有问题。你可以在小应用程序中尝试吗?我怀疑问题出在其他地方。
  • 在单独的 ResourceDictionary 上定义 DataTemplate。这种方式对我不起作用。

标签: wpf xaml datatemplate staticresource


【解决方案1】:

我猜这是因为:

StaticResource

  • 不支持前向引用
  • 程序启动时只设置一次:load-time资源查找

DynamicResource

  • 支持前向引用
  • 适用于对资源的每次访问:运行时查找

Example of forward reference

不适用于StaticResource

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

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

DynamicResource合作:

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

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

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

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

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

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

【讨论】:

  • @Theodore Zographos:是的,我想把它写在我的答案中,但只限于一段。
  • 好吧,至少在词汇上,我看不到前向引用,因为CoolNumbersColor 是在 MergedDictionaries 之前定义的。当解析器评估 DataTemplate 时,它​​应该找到 CoolNumbersColor,因为它是在查找链中定义的:1.same xaml 2.Generic.xaml 3.app.resources
  • @Theodore Zographos:在WPF中,元素首先从其资源部分寻找资源,然后冒泡到元素树的根部,最后到达系统主题,以下顺序说明顺序:1 . 元素层次结构。 2. Application.Resources 3. 类型主题 4. 系统主题。
  • @Theodore Zographos:它看起来像一个前向参考。当样式在本地可见时 - 它必须是静态的,如果不是 - 它是动态的。我在网上看到了这个说法,如果你愿意,我可以给你出处。
  • @Theodore Zographos:是的。 App.xaml 中的字典排在第一位,所有可用的资源对应用程序都是全局的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多