如何使用C#在WPF中将矩形移动到已调整大小的父矩形旁边
本文关键字:调整 移动 何使用 WPF | 更新日期: 2023-09-27 18:21:54
我是WPF的新手。我正在画布上单击按钮添加一个接一个的矩形。当我从文本框设置特定矩形的高度时。它与子矩形重叠。
例如:
当Height=100
、Width=200
&当我设置CCD_ 3的高度时。则子CCD_ 4必须出现在第二矩形&不得重叠在第三个矩形上。有可能吗
static int val=0;
List<UIElement> itemstoremove = new List<UIElement>();
private void BtnAdd_Click(object sender, RoutedEventArgs e)
{
int heigt = 0;
int wegt = 0;
if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
{
heigt = int.Parse(txtHeight.Text);
wegt = int.Parse(txtWidth.Text);
}
rect = new Rectangle();
rect.Stroke = Brushes.Red;
rect.StrokeThickness = 2;
rect.Height = heigt;
rect.Width = wegt;
Canvas.SetLeft(rect, 10);
Canvas.SetTop(rect, (rect.Height) * val);
rect.Tag = val;
canvasboard.Children.Add(rect);
val = val + 1;
//canvasboard is Canvas object
foreach (UIElement ui in canvasboard.Children)
{
if (ui.GetType() == typeof(Rectangle))
{
itemstoremove.Add(ui);
}
}
}
用于修改高度&宽度:
private void BtnModify_Click(object sender, RoutedEventArgs e)
{
int heigt = 0;
int wegt = 0;
if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
{
heigt = int.Parse(txtHeight.Text);
wegt = int.Parse(txtWidth.Text);
}
Rectangle rectToRemove;
foreach (UIElement ui in itemstoremove)
{
if (ui.GetType() == typeof(Rectangle) && ((Rectangle)ui).Tag.ToString() == txtModifyRect.Text)
{
rectToRemove = ui as Rectangle;
//itemstoremove.Remove(rectToRemove);
rectToRemove.Height = heigt;
rectToRemove.Width = wegt;
//canvasboard.Children.Remove(rectToRemove);
break;
}
}
}
这很好用我只想防止Rectangle
彼此重叠,并且必须通过自动调整一个接一个地出现
感谢帮助!
为了获得想要的效果,必须将画布更改为WrapPanel。这样,当您将子对象添加到画布时,就不会添加位置,而是会自行排列对象。基本上你想要这个
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<WrapPanel Name="objList" > </WrapPanel>
</ScrollViewer>
如果您的对象数量超过窗口所能容纳的数量,ScrollViewer将允许您滚动。
是否需要具体为Canvas
。。?即使在纯WPF/Desktop中,也有一些布局组件可以完全自动地为您做到这一点。
一个接一个地"堆叠"组件的行为正是StackPanel
类/组件/控件所做的:
<StackPanel x:Name="stacker" Orientation="Vertical">
<Rectangle Width="30" Height="100" Background="Green" />
<Rectangle Width="10" Height="50" Background="Blue" />
<Rectangle Width="20" Height="80" Background="Red" Margin="5,10" />
</StackPanel>
注意矩形是如何根据其不同的Heights
一个接一个地定位的。请注意,我不必指定Orientation=Vertical
,因为StackPanel的默认行为是这样定位它们。如果你愿意,你可以将其切换到Horizontally,然后它会根据它们的Widths
进行堆叠。您也可以微调并添加一些额外的间距,例如Margin
,如第三个矩形。
如果你需要通过代码来完成,那么名为stacker
的StackPanel
非常适合它:你可以动态地向它添加新元素,它会像在XAML中定义的子元素一样排列添加的元素:一个在另一个下面。
使用StackPanel,您可以获得更多!StackPanel观察其子对象。如果在放置孩子后的某个时间,您更改了孩子的高度/宽度,那么StackPanel会立即调整位置,使它们不会重叠(如果您使孩子变小,它会挤压他们,如果您使儿童变大,它会膨胀等)。
如果您真的想使用Canvas
,那么在添加一个新项目时,您必须循环浏览画布中存储的所有现有项目,求出它们的高度,并将新项目的Y位置设置为,正好是该总和。这样,它将恰好出现在最后一个元素下。这是最明显的方法。然而,它不会考虑可能出现在画布上的边距、间距和其他一些精细细节。
一个更好但不太明显的方法是不要一次又一次地总结高度,而是根据最底部的现有项目来定位新项目。毕竟,所有的旧物品都放置得很好,对吧?但是,bottommost
是什么意思?有时,位于顶部附近的高物品可能比位于中心的不那么高的物品更向下。因此,bottommost
并不意味着the item with maximum Y position
,而是意味着具有最远Bottom
的项目,因此maximum Y+Height
。因此:
- 循环浏览现有项目
- 查找
Size.Height+Position.Bottom
最大的项目 - 将新项目的
Position.Y
设置为该值
现在,您将获得与StackPanel大致相同的效果,但这只是一次性效果。如果以后修改某些图元的高度,则必须重新计算所有位置并调整所有位置。。(*)
编辑:(*)我记不清了,但如果X/Y/Bottom属性是DependencyProperty,那么您甚至可以尝试使用Bindings来自动控制位置。在画布上做这件事可能很有趣。只需尝试将后一个元素的Y
绑定到前一个的Bottom
,就可以神奇地自行布局,甚至在移动/调整大小时自动更新。不过,请先试试StackPanel!
听起来你想要一个StackPanel
作为你的矩形。您可以将StackPanel嵌套在网格中。
这是我的解决方案:
<ScrollViewer VerticalScrollBarVisibility="Auto" Width="250" Height="500">
<WrapPanel Name="wrapboard" Orientation="Vertical" ></WrapPanel>
</ScrollViewer>
private void BtnAdd_Click(object sender, RoutedEventArgs e)
{
int heigt = 0;
int wegt = 0;
if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
{
heigt = int.Parse(txtHeight.Text);
wegt = int.Parse(txtWidth.Text);
}
rect = new Rectangle();
rect.Stroke = Brushes.Red;
rect.StrokeThickness = 2;
rect.Height = heigt;
rect.Width = wegt;
rect.Tag = val;
wrapboard.Children.Add(rect);
val = val + 1;
//wrapboard is WrapPanel object
foreach (UIElement ui in wrapboard.Children)
{
if (ui.GetType() == typeof(Rectangle))
{
itemstoremove.Add(ui);
}
}
}