我自己遇到这个问题后,正在阅读 Rohit Vats 对 this 帖子的回答,并且想知道为什么 UserControl 的“父”窗口不被视为其逻辑父窗口。他继续解释解析行为,但这根本不是问题。问题在于,在非常明显的元素层次结构中,由于某种原因,直观上被视为子元素的控件显然不在 WPF 中。
窗口是其逻辑树中包含的所有元素的逻辑祖先。
这很容易检查:
<Window x:Class="Core2024.SO.CyrilCommando.question79128735.CheckAncestorWindow"
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"
xmlns:local="clr-namespace:Core2024.SO.CyrilCommando.question79128735"
mc:Ignorable="d"
Title="CheckAncestorWindow" Height="450" Width="800">
<Window.Resources>
<Point x:Key="point">200 100</Point>
</Window.Resources>
<Grid>
<UserControl>
<Button Content="Find point" Click="OnFind"/>
</UserControl>
</Grid>
<x:Code>
<![CDATA[
private void OnFind(object sender, RoutedEventArgs e)
{
FrameworkElement? curr = (Button)sender;
while(curr is not null && curr is not Window)
{
curr = curr.Parent as FrameworkElement;
}
string message = curr is null
? "Window not found"
: $"Window found. Point = {curr.Resources["point"]}" ;
MessageBox.Show(message);
}
]]>
</x:Code>
</Window>
我认为你更准确的问题应该是:“为什么 UserControl 中的 StaticResource 标记扩展找不到使用此 UserControl 的窗口的资源?”
问题是 StaticResource 在初始化属性时就确定(解析)了。对于 UserControl,这与调用 InitializeComponent() 一致;代码隐藏中的方法。该方法在构造函数中调用。但此时,UserControl 实例尚未添加到 Window,因此 Window 还不是其父级。
例如,如果您使用DynamicResource,它将能够毫无问题地从父窗口找到资源。因为它会动态确定资源,并在可视化树发生变化时重新搜索它们。因此,将 UserControl 添加到 Window 后,DynamicResource 将再次开始搜索资源,并且能够在 Window 的资源中找到它。