我的印象是,听Loaded event可以确保我可以在那时访问视觉树。这似乎在大多数情况下都可以正常工作,而视觉树正是我所期望的。但是,当使用TabControl时,隐藏选项卡上的控件在加载的事件触发之前不会构建其可视树。

举一个简单的例子:

<Window ...>
    <Grid>
        <TabControl>
            <TabItem Header="Tab 1">
                <my:MyTextBox />
            </TabItem>
            <TabItem Header="Tab 2">
                <my:MyTextBox />
            </TabItem>
        </TabControl>
    </Grid>
</Window>


MyTextBox是一个自定义组件,仅在发生某些事件时注销。

public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        Loaded += (s,e) => {
            Console.WriteLine("MyTextBox {0}: Loaded", s.GetHashCode());
            Dispatcher.BeginInvoke(()=>Console.WriteLine("MyTextBox {0}: Loaded BeginInvoke", s.GetHashCode()));
        };
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        Console.WriteLine("MyTextBox {0}: OnApplyTemplate", this.GetHashCode());
    }
}


这是输出:

MyTextBox A: OnApplyTemplate
MyTextBox A: Loaded
MyTextBox B: Loaded
MyTextBox A: Loaded BeginInvoke
MyTextBox B: Loaded BeginInvoke
(changing tab to 2)
MyTextBox B: OnApplyTemplate
MyTextBox B: Loaded
MyTextBox B: Loaded BeginInvoke


如您所见,对于位于第二个选项卡上的B,仅当您切换到其选项卡时才执行OnApplyTemplate,但实际上已加载的事件实际上是在之前引发的。

现在的问题是,我的自定义组件是一个具有外观控件组件的外观组件。在加载的事件中,我现在想遍历视觉树并应用一些其他默认值,但是由于尚未应用模板,因此视觉树为空。

是否有某种方式可以从外部(即不修改组件)确保我可以在视觉树加载后立即对其进行遍历?

最佳答案

TabControl在后台进行了一些虚拟化。
您可以根据此SO问题的答案禁用此功能:
How to preserve control state within tab items in a TabControl

关于wpf - OnApplyTemplate之前的已加载事件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12620953/

10-17 01:04