在调查我正在处理的应用程序的问题时,我遇到了一个我不太理解的行为。例如,当你有一个带有绑定文本属性的TextBox时,系统似乎比你有一个静态文本多了一次布局过程。
谁能解释一下为什么会出现这种额外的通行证?引擎是否先放置未绑定的控件,然后绑定它,然后再放置它?
为了测试这一点,我构建了这样的测试用例:
我声明了一个继承自TextBox的类(因此我可以覆盖ArrangeOverride):
public class MultiBoundTextBox : TextBox
{
protected override Size ArrangeOverride(Size arrangeBounds)
{
Console.WriteLine("TextBox.Arrange");
return base.ArrangeOverride(arrangeBounds);
}
}然后我在一个窗口中放置了这个文本框的一个实例:
<local:MultiBoundTextBox x:Name="tb">
Some text
</local:MultiBoundTextBox>并为测试窗口添加了一些代码:
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;
}现在,当我运行这个命令时,我得到了这个输出:
Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded但如果我将Text属性更改为像这样绑定:
<local:MultiBoundTextBox x:Name="tb">
<Binding Path="Day" Mode="OneWay" />
</local:MultiBoundTextBox>我在输出中得到了如下结果:
Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded注意额外的一对TextBox.Arrange和Window.Arrange。为什么需要额外的通行证?
发布于 2009-09-03 09:43:50
引擎是否先放置未绑定的控件,然后绑定它,然后再放置它?
事实可能的确如此- WPF data binding在很大程度上建立在Dependency Properties之上,这实际上会影响WPF布局过程,请参阅Layout Performance Considerations
其值可能导致布局系统初始化的
依赖属性使用公共标志进行标记。AffectsMeasure和AffectsArrange提供了有关哪些属性值更改将强制布局系统进行递归更新的有用线索。通常,任何可以影响元素边界框大小的属性都应该将AffectsMeasure标志设置为true。详情请参考Dependency Properties Overview。
具体来说,关于您的问题,请参阅Optimizing Performance: Layout and Design的引文
如果发生以下任一操作,将再次调用布局过程:
因此,我可以想象,最初的布局过程与稍后更改绑定值的用例没有任何不同,这将解释您正在经历的行为。虽然这可能仍然是优化启动体验的一个错失的机会,但通常的优化警告适用于:没有测量就没有优化-例如,这种假定的冗余(如果在技术上完全可以避免)可能没有可测量的影响,因为窗口/控件尚未显示等。
调试:
要添加到Drews suggestion of a debugging aid上,在.NET Framework3.5中引入了一个与绑定相关的新的专用调试辅助工具,请参阅PresentationTraceSources.TraceLevel - example:
<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>不过,要实现这一点有一些限制,请务必阅读PresentationTraceSources Class中的部分备注。
发布于 2009-09-02 13:29:29
不是直接的答案,但是如果您向绑定添加一个转换器,该转换器除了写出一条消息来显示绑定的求值时间之外,什么也不做,那该怎么办呢?
public sealed class LoggingConverter : IValueConverter
{
public void Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
Console.WriteLine("Binding.Convert");
return value;
}
public void ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
Console.WriteLine("Binding.ConvertBack");
return value;
}
}https://stackoverflow.com/questions/734519
复制相似问题