为何代码无法将新增控件放置在TextBlock之外?
问题排查与修复
你的代码里Rect.Intersect判断不生效、MessageBox没触发,核心原因和修复方案如下:
主要问题点
TextBlock的实际尺寸未正确计算
在window_Loaded触发时,WPF的布局系统可能还没完成TextBlock的渲染,导致textBlock1.ActualWidth和textBlock1.ActualHeight都是0。这样生成的textblock_rect是个位置正确但尺寸为0的矩形,根本不可能和星星的矩形相交,判断条件自然永远不成立。相交判断的写法不够可靠
用Rect.Intersect返回的区域和Rect.Empty比较,可能会因为浮点数精度问题出现误判。直接用Rect.IntersectsWith()方法返回的布尔值判断相交,逻辑更直观也更可靠。不必要的Canvas操作
当前代码先把星星加到Canvas,判断相交后又移除,反复操作会浪费性能。应该先算好位置尺寸、确认不相交后再添加到Canvas。
修复步骤
1. 确保TextBlock获取正确尺寸
在获取TextBlock的尺寸前,强制触发它的布局计算。可以在window_Loaded里调用add_mini_star之前加这段代码:
// 强制TextBlock完成布局计算 textBlock1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); textBlock1.Arrange(new Rect(textBlock1.DesiredSize));
2. 替换相交判断逻辑
把原来的Rect.Intersect判断改成IntersectsWith:
// 替换原来的if条件 if (mini_star_rect.IntersectsWith(textblock_rect)) { MessageBox.Show("problem"); ___Canvas1_.Children.Remove(mini_star); goto try_again; }
3. 优化Canvas操作顺序
先计算星星的位置和尺寸,检查完相交后再添加到Canvas,避免反复添加移除:
try_again: var star_size = rnd.Next(10, 40); mini_star.Width = star_size; mini_star.Height = star_size; // 先计算位置 double left = rnd.Next(0, (int)(900 - star_size)); double top = rnd.Next(0, (int)(700 - star_size)); // 生成星星的矩形 Rect mini_star_rect = new Rect(left, top, star_size, star_size); // 生成TextBlock的矩形(确保尺寸已正确计算) Rect textblock_rect = new Rect(Canvas.GetLeft(textBlock1), Canvas.GetTop(textBlock1), textBlock1.ActualWidth, textBlock1.ActualHeight); // 判断相交 if (mini_star_rect.IntersectsWith(textblock_rect)) { MessageBox.Show("problem"); goto try_again; } // 确认不相交后再添加到Canvas Canvas.SetLeft(mini_star, left); Canvas.SetTop(mini_star, top); ___Canvas1_.Children.Add(mini_star); mini_star.Opacity = 0; mini_stars.Add(mini_star);
完整修改后的关键代码
public void add_mini_star() { System.Windows.Controls.Image mini_star = new System.Windows.Controls.Image(); mini_star.Source = new BitmapImage(new Uri(@"/Star.png", UriKind.RelativeOrAbsolute)); mini_star.Visibility = Visibility.Visible; try_again: var star_size = rnd.Next(10, 40); mini_star.Width = star_size; mini_star.Height = star_size; double left = rnd.Next(0, (int)(900 - star_size)); double top = rnd.Next(0, (int)(700 - star_size)); Rect mini_star_rect = new Rect(left, top, star_size, star_size); // 确保TextBlock尺寸正确 textBlock1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); textBlock1.Arrange(new Rect(textBlock1.DesiredSize)); Rect textblock_rect = new Rect(Canvas.GetLeft(textBlock1), Canvas.GetTop(textBlock1), textBlock1.ActualWidth, textBlock1.ActualHeight); if (mini_star_rect.IntersectsWith(textblock_rect)) { MessageBox.Show("problem"); goto try_again; } Canvas.SetLeft(mini_star, left); Canvas.SetTop(mini_star, top); ___Canvas1_.Children.Add(mini_star); mini_star.Opacity = 0; mini_stars.Add(mini_star); } private void window_Loaded(object sender, RoutedEventArgs e) { sb1 = (Storyboard)FindResource("Storyboard1"); // 提前初始化TextBlock布局 textBlock1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); textBlock1.Arrange(new Rect(textBlock1.DesiredSize)); for (int x = 0; x < 32; x++) { add_mini_star(); } DoubleAnimation[] start_anims = new DoubleAnimation[32]; for (int x = 0; x < 32; x++) { start_anims[x] = new DoubleAnimation(); start_anims[x].From = 0; start_anims[x].To = 1; start_anims[x].Duration = new TimeSpan(0, 0, 3); start_anims[x].BeginTime = new TimeSpan(0, 0, 4); start_anims[x].FillBehavior = FillBehavior.Stop; start_anims[x].Completed += OnCompleted; mini_stars[x].BeginAnimation(OpacityProperty, start_anims[x]); } sb1.Begin(); }
内容的提问来源于stack exchange,提问作者ExCeed
相关产品推荐
相关产品推荐

