我曾经在调用InitializeComponent
之后在构造函数中放置了可见的初始化,尽管我注意到网络上的示例与此不一致:有些人在调用InitializeComponent
之前初始化。我最近注意到,即使此类初始化位于ContentRendered
事件中,它们仍然会及时显示,即使Windows Lifetime Events文档显示ContentRendered
已经很晚了。事实上,这个名字暗示为时已晚:Content Rendered
是过去式。以下代码具有预期的行为表明内容在事件发生时尚未真实完整地呈现,并且ContentRendered
发生的时间早于名称所示。如果它还相当早,那么就会提出一个问题,即为什么我们需要使用Loaded
,这也比完整渲染更早?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ContentRenderedEvent(object sender, EventArgs e)
{
Label1.Content = "This is Label1";
TextBox1.Text = "hello";
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
ContentRendered="ContentRenderedEvent">
<StackPanel>
<Label x:Name="Label1" Margin="5"
Width="100" Height="30">not initialized</Label>
<TextBox Margin="5" x:Name="TextBox1" Width="60" Height="30"></TextBox>
</StackPanel>
</Window>
答案 0 :(得分:1)
即使ContentRendered
实际上已经太晚了,您正在初始化的属性(Label.Content
,TextBox.Text
)也是DependencyProperties
。无论何时更改框架都会进行交易,这会强制更新UI。那个(加上绑定)是完全拥有它们的重点,而不是简单的自动道具和简单的get / set对。
所以,当你在ContentRendered
中分配它们时,那么:
与您在Loaded中执行此操作相比:
这是一个粗略的草图,但你应该看到明显的差异。关键点是:
ContentRendered
事件中捕获视图的某些状态 - 例如,您可以通过编程方式将当前视图另存为PNG,以便能够看到确切的中间状态TextBox.Text
) - 并检查他们的标志。如果您看到AffectsRender/Measure/Arrange
之类的内容。然后更改它们将触发几乎立即更新/重绘。所有三个标志都很重要。 “内容”类属性(文本,内容,数据源,项目......)几乎总是用AffectsMeasure
标记,因为改变内容通常不仅要强制绘画,还要重新制作完整的布局周期每次改变价值观。 “风格”型道具(前景,背景,填充,画笔,......)通常只有AffectsRender
,因为重绘足够,布局可以是相同的。等等。 More on that i.e. here on excellent Dr.WPF blog。虽然它是关于Silverlight的,但基础仍然适用。