我是WPF的新手。我在Canvas上按钮单击一个接一个地添加矩形。当我从TextBox设置特定矩形的高度。它与Child Rectangle重叠。
例如:。 当有3个带有{{1}},Height=100
&的矩形时当我设置Width=200
的高度时。那么孩子Second Rectangle to 150
必须出现在第二个矩形&不得重叠第三个矩形。可能吗?
Rectangle
修改高度&宽度:
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;
}
}
}
相互重叠,并且必须使用自动调整逐个显示。
帮助感谢!
答案 0 :(得分:1)
为了获得您想要的效果,您必须将Canvas更改为WrapPanel。 这样,当您将子项添加到画布时,您不会添加位置,它会自行排列对象。 基本上你想要这个
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<WrapPanel Name="objList" > </WrapPanel>
</ScrollViewer>
如果您拥有的对象多于窗口可以包含的对象,则ScrollViewer将允许您滚动。
答案 1 :(得分:1)
是否需要具体Canvas
..?即使在纯WPF /桌面中,也有一些布局组件可以为您完成此操作,强制自动。
&#34;堆叠&#34;的行为一个接一个的组件正是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的默认行为是将它们放置在那里。您可以根据需要将其切换为水平,然后根据Widths
将它们堆叠起来。您还可以使用Margin
进行微调并添加一些额外的间距,如第三个矩形所示。
如果您需要通过代码执行此操作,那么名为StackPanel
的{{1}}非常适合它:您可以动态添加新元素,它会像添加它一样添加新元素在XAML中定义的子项:一个在另一个下面。
使用StackPanel可以获得更多! StackPanel观察它的孩子。如果在放置孩子之后的某个时间你改变孩子的高度/宽度,那么StackPanel会立即调整位置,这样他们就不会重叠(如果你让孩子变小,它会挤压他们,如果你让孩子大 - 它将扩大等)。
如果你真的真的想要使用stacker
,那么在添加一个新项目的那一刻,你将不得不遍历存储在画布中的所有现有项目,总结他们的高度,并将新项目的Y位置设置为完全相同的总和。这样,它将在最后一个元素下显示。这是最明显的做法。但是,它不会考虑可能恰好在您的画布上的边距,间距和一些其他精细细节。
更好但不太明显的方法是不要一次又一次地总结高度,而是根据最底层的现有项目来定位新项目。毕竟,所有旧物品都放置得恰到好处,对吧?但是,Canvas
是什么意思?有时,位于顶部附近的高大项目可能比位于中心的不太高的项目更向下跨越。因此,bottommost
并不意味着bottommost
,而是指具有最远the item with maximum Y position
的项目,因此Bottom
。所以:
maximum Y+Height
最大的项目Size.Height+Position.Bottom
设置为该值现在,您将获得与StackPanel大致相同的功能 - 但它只会产生一次性效果。如果您稍后修改某些元素的高度,则必须重新计算所有位置并调整所有位置。(*)
编辑:
(*)我不记得确切,但如果X / Y / Bottom属性是DependencyProperty,那么你甚至可以尝试使用Bindings自动控制位置。在Canvas上做Tha可能很有趣。只是尝试将后一个元素的Position.Y
绑定到前者的Y
,它们应该神奇地布局自己,甚至在移动/调整大小时自动更新。不过,请先试试StackPanel!
答案 2 :(得分:0)
听起来你想要一个StackPanel
的矩形。您可以将StackPanel嵌套在Grid中。
答案 3 :(得分:0)
这是我的解决方案:
<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);
}
}
}