Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# UIElement在哪一点加载?_C#_Wpf_Loaded - Fatal编程技术网

C# UIElement在哪一点加载?

C# UIElement在哪一点加载?,c#,wpf,loaded,C#,Wpf,Loaded,我有以下代码: <Window x:Class="Demo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.m

我有以下代码:

<Window x:Class="Demo.MainWindow"
        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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas Name="Canvas_Main" />
</Window>


公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
加载+=主窗口\u加载;
}
已加载私有void主窗口(对象发送器、路由目标)
{
矩形lastRectangle=null;
随机数=新随机数(0);
用于(Int32计数器=0;计数器<5;计数器++)
{
矩形=新矩形();
矩形。填充=画笔。蓝色;
矩形.Width=random.Next(100200);
矩形。高度=计数器*100;
Canvas_Main.Children.Add(矩形);
if(lastRectangle==null){
Canvas.SetLeft(矩形,0);
Canvas.SetTop(矩形,0);
}
其他的
{
SetLeft(矩形,lastRectangle.ActualWidth);
Canvas.SetTop(矩形,0);
}
lastRectangle=矩形;
}
}
}
这没有按预期工作(将每个矩形彼此对角放置),因为
lastRectangle.ActualWidth
为0。据我所知,这是因为lastRectangle没有被测量和排列


我很好奇,如果添加到一个已经可见并已装载的容器中,测量和排列将在什么时候完成?窗口的测量和排列已经完成。但是您现在正在创建新的子控件,通常在窗口的下一个布局过程之前不会对其进行测量/排列


通过调用循环末尾每个矩形的
Measure
方法,可以立即强制执行此操作。

元素的
Framework.Loaded
事件在度量和排列布局过程之后,但在呈现元素之前引发

当在元素上调用异步布局过程的
UIElement.InvalidateMeasure
或同步布局过程的
UIElement.UpdateLayout
时,初始化完整布局过程

在您的场景中,将调用
Window.Loaded
事件处理程序,这意味着
Window
Canvas
都已加载(但未呈现)。
现在开始向
画布添加新的
UIElement
元素

Canvas.Children.Add
应调用
InvalidateMeasure
方法。由于
InvalidateMeasure
触发异步布局过程,因此
Canvas
和当前子元素将被排入布局队列,上下文将继续执行(添加更多矩形)。
由于新添加的元素已经有一个挂起的布局过程,因此应该避免手动调用
UIElement.Measure
(这是递归调用,在考虑性能时非常昂贵)

上下文完成后,队列中等待布局传递和最终呈现的元素将被处理,并对这些元素(
Canvas
及其子元素)递归调用
MeasureOverride
ArrangeOverride

因此,
UIElement.renderize
可以由布局系统计算。
此时,新的
框架元素.ActualWidth
将可用

这是添加元素(矩形)的
FrameworkElement.Loaded
事件最终引发的时刻

要解决您的问题,您必须使用
Rectangle.Width
代替
或者在添加下一个事件之前,等待每个
矩形.Laoded
事件:

private int ShapeCount { get; set; }
private const int MaxShapes = 5;
private Point ShapeBPosition { get; set; }

private void MainWindow_Loaded(Object sender, RoutedEventArgs e)
{
  this.ShapePosition = new Point();
  AddRectangle(this.ShapePosition);
}

private void AddRectangle(Point position)
{
  Random random = new Random();
  Rectangle rectangle = new Rectangle();
  rectangle.Fill = Brushes.Blue;

  rectangle.Width = random.Next(100, 200);
  rectangle.Height = ++this.ShapeCount * 100;

  Canvas_Main.Children.Add(rectangle);
  Canvas.SetLeft(rectangle, position.X);
  Canvas.SetTop(rectangle, position.Y);

  rectangle.Loaded += OnRectangleLoaded;
}

private void OnRectangleLoaded(object sender, RoutedEventArgs e)
{
  var rectangle = sender as Rectangle;

  rectangle.Loaded -= OnRectangleLoaded;
  if (this.ShapeCount == MainWindow.MaxShapes)
  {
    return;
  }

  // this.ShapePosition is struct => modify copy
  Point position = this.ShapePosition; 
  position.Offset(rectangle.ActualWidth, 0);
  this.ShapePosition = position;
  AddRectangle(this.ShapePosition);
}

非常感谢。但是,是什么导致调用窗口的布局方法呢?我无法想象这在计时器中运行,但添加或删除子项不会触发布局?如果您能扩展您的答案,我们将不胜感激。在每个UI应用程序的顶部都有一个
while
循环,它会反复运行,直到应用程序退出。布局过程是WPF循环执行的阶段之一。(为了避免您可能提出的下一个问题,请避免阻塞CPU内核。在操作系统提示循环继续之前,循环会一直处于空闲状态,例如,通知它用户输入。)谢谢-您为我提供了大量的方法和事件以查找更多详细信息。
private int ShapeCount { get; set; }
private const int MaxShapes = 5;
private Point ShapeBPosition { get; set; }

private void MainWindow_Loaded(Object sender, RoutedEventArgs e)
{
  this.ShapePosition = new Point();
  AddRectangle(this.ShapePosition);
}

private void AddRectangle(Point position)
{
  Random random = new Random();
  Rectangle rectangle = new Rectangle();
  rectangle.Fill = Brushes.Blue;

  rectangle.Width = random.Next(100, 200);
  rectangle.Height = ++this.ShapeCount * 100;

  Canvas_Main.Children.Add(rectangle);
  Canvas.SetLeft(rectangle, position.X);
  Canvas.SetTop(rectangle, position.Y);

  rectangle.Loaded += OnRectangleLoaded;
}

private void OnRectangleLoaded(object sender, RoutedEventArgs e)
{
  var rectangle = sender as Rectangle;

  rectangle.Loaded -= OnRectangleLoaded;
  if (this.ShapeCount == MainWindow.MaxShapes)
  {
    return;
  }

  // this.ShapePosition is struct => modify copy
  Point position = this.ShapePosition; 
  position.Offset(rectangle.ActualWidth, 0);
  this.ShapePosition = position;
  AddRectangle(this.ShapePosition);
}