WPF中的绑定和布局关系

Ala*_*ich 8 wpf layout binding

在调查我正在处理的应用程序的问题时,我遇到了一个我不太了解的行为.看起来当你有一个TextBox(例如)带有绑定的Text属性时,系统会比你有一个静态文本时多接受一次布局传递.

请问任何人,解释为什么会发生这个额外的通行证?引擎是否先放置未绑定的控件然后将其绑定然后再次放置它?

为了测试这个我构建了这样的测试用例:

我已经声明了一个继承自TextBox的类(所以我可以覆盖ArrangeOverride):

public class MultiBoundTextBox : TextBox
{
    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        Console.WriteLine("TextBox.Arrange");
        return base.ArrangeOverride(arrangeBounds);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我在窗口中放置了这个文本框的实例:

<local:MultiBoundTextBox x:Name="tb">
Some text
</local:MultiBoundTextBox>
Run Code Online (Sandbox Code Playgroud)

并为测试窗口添加了一些代码:

    public Window11()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("Window.Loaded");
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        Console.WriteLine("Window.Arrange");
        return base.ArrangeOverride(arrangeBounds);
    }

    private void Window_Initialized(object sender, EventArgs e)
    {
        Console.WriteLine("Window.Initialized");
        tb.DataContext = DateTime.Now;
    }
Run Code Online (Sandbox Code Playgroud)

现在,当我运行这个时,我得到了这个输出:

Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded
Run Code Online (Sandbox Code Playgroud)

但是,如果我将Text属性更改为这样绑定:

    <local:MultiBoundTextBox x:Name="tb">
        <Binding Path="Day" Mode="OneWay" />
    </local:MultiBoundTextBox>
Run Code Online (Sandbox Code Playgroud)

我在输出中得到了这个:

Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded
Run Code Online (Sandbox Code Playgroud)

注意额外的TextBox.Arrange和Window.Arrange对.为什么需要这个额外的通行证?

Ste*_*pel 2

引擎是否先放置未绑定的控件,然后绑定它,然后再次放置它?

情况可能确实如此 - WPF 数据绑定很大程度上构建在Dependency Properties之上,这实际上会影响 WPF 布局过程,请参阅布局性能注意事项

其值可以导致布局系统初始化的依赖属性用公共标志进行标记。AffectsMeasureAffectsArrange提供了有用的线索,说明哪些属性值更改将强制布局系统进行递归更新。一般来说,任何可以影响元素边界框大小的属性都应将 AffectsMeasure标志设置为 true。有关更多信息,请参阅依赖属性概述

特别是关于您的问题,请参阅优化性能:布局和设计的引文:

如果发生以下任一操作,则会再次调用布局传递过程:

  • [...]
  • 当使用影响度量或排列通道的元数据标记的依赖项属性的值发生更改时。

因此,我可以想象初始布局过程与后来绑定值更改的用例没有任何不同,这可以解释您所经历的行为。虽然这可能仍然是优化启动体验的一个错失机会,但通常的优化警告适用:没有测量就没有优化- 例如,这种假设的冗余(如果技术上完全可以避免)可能不会产生可测量的影响,因为窗口/控件尚未被调整。显示等


调试:

为了添加 Drews建议的调试辅助工具,在 .NET Framework 3.5 中引入了一个与绑定相关的新的专用调试辅助工具,请参阅PresentationTraceSources.TraceLevel示例:

<Window ... xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase">
    <local:MultiBoundTextBox x:Name="tb">
        <Binding Path="Day" Mode="OneWay"
                 diag:PresentationTraceSources.TraceLevel="High"/>
    </local:MultiBoundTextBox>
</Window>
Run Code Online (Sandbox Code Playgroud)

不过,此操作有一些限制,请务必阅读中的“备注”PresentationTraceSources Class部分。