为什么 WPF UserControl 的宿主窗口不被视为其逻辑父窗口?

问题描述 投票:0回答:1

我自己遇到这个问题后,正在阅读 Rohit Vats 对 this 帖子的回答,并且想知道为什么 UserControl 的“父”窗口不被视为其逻辑父窗口。他继续解释解析行为,但这根本不是问题。问题在于,在非常明显的元素层次结构中,由于某种原因,直观上被视为子元素的控件显然不在 WPF 中。

c# .net wpf xaml user-controls
1个回答
0
投票

窗口是其逻辑树中包含的所有元素的逻辑祖先。

这很容易检查:

<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 的资源中找到它。

© www.soinside.com 2019 - 2024. All rights reserved.