为什么在这种情况下无法解析StaticResource?

15

我遇到了一个异常"Cannot find resource named 'mrg'. Resource names are case sensitive.",当我尝试执行以下操作时:

MainWindow.xaml:


MainWindow.xaml:

<Window.Resources>
  <Thickness Left="0"
             Right="1"
             Bottom="2"
             Top="3"
             x:Key="mrg" />
</Window.Resources>
<Grid>
  <ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <local:UserControl1 />
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</Grid>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        List<string> source = new List<string>()
        {
            "item1",
            "item2",
            "item3",
            "item4",
            "item5",
        };
        DataContext = source;
    }
}

和UserControl1.xaml:

<Grid>
    <TextBlock Text="{Binding}" Margin="{StaticResource mrg}" />
</Grid>
根据 msdn 文章,静态资源查找行为如下:
  1. 查找过程在由设置该属性的元素定义的资源字典中检查请求的键。

  2. 然后,查找过程向上遍历逻辑树,到父元素及其资源字典。 这将继续,直到达到根元素。

  3. 接下来,会检查应用程序资源。 应用程序资源是指在 WPF 应用程序的 Application 对象所定义的资源字典中的那些资源。

因此,由于第2步,必须找到该资源。 但是,当异常被捕获时,我可以在 Locals 窗口中看到 UserControl1.Parent == null。
我对这个问题感到困惑。 我可以解决它的方式是将资源放到应用程序级别。
我的问题是:为什么找不到 StaticResource?
3个回答

17

DataTemplate形成了它自己的逻辑树,与ItemsControl的逻辑树不相连。因此,通过遍历逻辑树查找资源是找不到的。

我在MSDN上没有找到相关的参考资料,只看到了CodeProject上的这篇文章,其中写道:

作为扩展模板的一部分的元素,在这里称为“模板元素”,形成了它们自己的逻辑树,这棵逻辑树与创建它们的对象的逻辑树不相连。


使用DynamicResource而不是StaticResource可以解决这个问题。但是我无法确切地说明为什么。也许可以在静态和动态资源的“静态资源查找行为”和“动态资源查找行为”部分中找到说明,但我不确定。


好的建议,我会继续调查这个问题。 - stukselbax
在我的情况下,我通过将资源字典合并到需要它的窗口或用户控件内部来修复它,而不是在App.xaml中“全局”合并它。在设计时一切都看起来很好,但在运行时却出现了这个异常,所以有点令人困惑。 - angularsen
@SoMoS,你是在使用某种IoC吗?我曾经遇到过同样的问题,改用Dynamic解决了。我正在使用MEF通过名称约定从TViewModel中加载视图。 - BrunoLM
在这种特定情况下,我没有使用它:\ - Ignacio Soler Garcia
DynamicResource在我尝试时确实起作用了,但由于它似乎是在运行时绑定的,所以我对使用它感到有些担忧。在我的情况下,事实证明我在声明顺序上犯了一个新手错误,在阅读了这里的答案后进行了修复:如何从DataTemplate内部引用静态资源 - mungflesh

3

在代码清理后,我遇到了类似的问题。代码看起来和编译都没问题,但运行时会产生“未找到StaticResource”的错误。

将StaticResource更改为DynamicResource确实有效。但最终是由于App.xaml中在<ResourceDictionary.MergedDictionaries>部分下添加资源字典的顺序造成的。


2

在引用静态资源之前必须先定义它们。

当XAML解析器遇到未知的静态资源链接时,会抛出异常。(可以通过使用动态资源来解决此问题,但会带来额外的成本)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接