gpt4 book ai didi

c# - 修改wpf中任何矩形的高度后如何在 Canvas 上重新排列矩形?

转载 作者:行者123 更新时间:2023-11-30 20:56:14 25 4
gpt4 key购买 nike

我正在从用户直接在网格行中输入的网格单元格值中添加 Rectangle。当我修改特定列的值时说 ThicknessHeight 然后它会增加所选行矩形的 Height 但它不会重新排列它下面的所有矩形在选定的行矩形之后。

在 xaml.cs 中

public class MyLayer : INotifyPropertyChanged 
{

public string Thickness { get; set; }
public string OffsetRight { get; set; }
public string OffsetLeft { get; set; }
public string Material { get; set; }
public string MaterialPopup { get; set; }
public Rectangle rectangle { get; set; }

public GlassRectangle GlassRectangle { get; set; }
public MaterialLayer()
{
GlassRectangle = new GlassRectangle();

}
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { }
remove { }
}
}

public class GlassRectangle
{

public Rectangle Rectangle { get; set; }
public double Top = 0;
public GlassRectangle()
{
Rectangle = new Rectangle();

}
}

private void gridInner_CellValueChanged(object sender, DevExpress.Xpf.Grid.CellValueChangedEventArgs e)
{
string cellValue = string.Empty;
MyLayer currentLayer = ((MyLayer)(e.Row));

if (e.Column.HeaderCaption.ToString() == "Thickness")
{

cellValue =(e.Value.ToString());
//there is alredy a rectangle - means this is edit mode
if (currentLayer.rectangle != null)
{
currentLayer.rectangle.Height = Convert.ToDouble(cellValue);
currentLayer.rectangle.Stroke = new SolidColorBrush(Color.FromRgb(0, 255, 0));

}
//else this is insert mode
else
{

currentLayer.rectangle = CreateRectangle(cellValue);
}

}

}

protected Rectangle CreateRectangle(string cellval)
{
Rectangle newrect = new Rectangle();
newrect.Stroke = Brushes.Red;
newrect.StrokeThickness = 1;
if (cellval.ToString().Contains("."))
{
newrect.Height = Convert.ToDouble(cellval) * 100;
}
else
{
newrect.Height = Convert.ToDouble(cellval);
}
newrect.Width = width;
Canvas.SetLeft(newrect, 100);
double canvasTop = 0.0;
if (canvasboard.Children.Count > 0)
{
var lastChildIndex = canvasboard.Children.Count - 1;
var lastChild = canvasboard.Children[lastChildIndex] as FrameworkElement;
if (lastChild != null)
//lastChild.Height-1: so that it come extactly on existing if set to +1 it comes below first rectangle
canvasTop = Canvas.GetTop(lastChild) + lastChild.Height - 1;
}

Canvas.SetTop(newrect, canvasTop);
val = val + 1;
newrect.Tag = val;
canvasboard.Children.Add(newrect);
//rectangle = rect;

foreach (UIElement ui in canvasboard.Children)
{
if (ui.GetType() == typeof(Rectangle))
{
itemstoremove.Add(ui);
}
}

return newrect;
}

新事件方法:

private void gridMaterialInner_CellValueChanged(object sender, DevExpress.Xpf.Grid.CellValueChangedEventArgs e)
{
string cellValue = string.Empty;
string cellOldValue = string.Empty;
MyLayer currentLayer = ((MyLayer)(e.Row));
if (e.Column.HeaderCaption.ToString() == "Thickness")
{
//current cell value
cellValue =(e.Value.ToString());// GetRowCellValue(e.RowHandle, gridMaterialInner.Columns["LastName"]).ToString();
//there is alredy a rectangle - means this is edit mode
double currentheight = 0.0;
double oldht = 0.0;
// old cell value
if (e.OldValue != null)
{
cellOldValue = (e.OldValue.ToString());
}
if (currentLayer.rectangle != null)
{
if (cellValue.ToString().Contains("."))
{
currentheight = Convert.ToDouble(cellValue) * 100;
}
else
{
currentheight = Convert.ToDouble(cellValue) * 100;
}
if (cellOldValue.ToString().Contains("."))
{
oldht = Convert.ToDouble(cellOldValue) * 100;
}
else if(cellOldValue!=string.Empty)
{
oldht = Convert.ToDouble(cellOldValue) * 100;
}

currentLayer.rectangle.Height = currentheight;
currentLayer.rectangle.Stroke = new SolidColorBrush(Color.FromRgb(0, 255, 0));

//Refresh();
//Get the index of selected row
int layerIndex = materialBindlist.IndexOf(currentLayer);
for(int i = layerIndex; i < materialBindlist.Count-1; i++)
{
//set the top position of all other rectangles that are below selected rectangle/row
//(Current-Old)+Top
Canvas.SetTop(materialBindlist[i + 1].rectangle, (currentheight - oldht) + materialBindlist[i + 1].GlassRectangle.Top);
//Canvas.SetTop(materialBindlist[i].rectangle, (currentheight - oldht) + materialBindlist[i + 1].GlassRectangle.Top);

}
}
//else this is insert mode
else
{
//MaterialLayer object
currentLayer.rectangle = CreateRectangle(cellValue);
//store Top & Rectangle object in GlassRectangle class which is referenced in MaterialLayer class
currentLayer.GlassRectangle.Rectangle = currentLayer.rectangle;
currentLayer.GlassRectangle.Top = canvasTop;
}

}

}

这会像 Canvas 上的堆叠项目一样一个接一个地创建矩形。但是当我修改 Thickness 列的值时,它是 RectangleHeight 它反射(reflect)在 Canvas 上,但下面的其他矩形必须出现在 Changed Height 之后当前矩形。

注意:我不能在我的应用程序中使用 WrapPanel。仅使用 Canvas 修改现有代码。

感谢帮助!

修改 CellChange 事件中的 For 循环:

int layerIndex = materialBindlist.IndexOf(currentLayer);
for(int i = layerIndex; i < materialBindlist.Count-1; i++)
{
//set the top position of all other rectangles that are below selected rectangle/row
//(Current-Old)+Top
double top=Convert.ToDouble((currentHeight - oldHeight) + materialBindlist[i + 1].GlassRectangle.Top);
Canvas.SetTop(materialBindlist[i + 1].rectangle,top);

materialBindlist[i + 1].GlassRectangle.Top = top;



}

最佳答案

即使使用 Canvas 也可以完成您正在寻找的内容但是你真的应该考虑使用类似 ItemsControl 的东西为此。

强制使用时的解决方案Canvas :

private void Refresh() {
for (int i = 1; i < canvasboard.Children.Count; ++i) {
var currentElement = canvasboard.Children[i] as FrameworkElement;
var previousElement = canvasboard.Children[i - 1] as FrameworkElement;
if (currentElement == null || previousElement == null)
return;
var requiredTop = Canvas.GetTop(previousElement) + previousElement.Height - 1;
if (Math.Abs(Canvas.GetTop(currentElement) - requiredTop) > 0.0)
Canvas.SetTop(currentElement, requiredTop);
}
}

现在在您更改 Canvas 中现有元素的大小“之后”调用此函数它将相应地重新定位元素以适应新的维度。在您的代码中,它将从 gridInner_CellValueChanged(...) 调用在“编辑”模式下设置新高度后的功能。

您应该尝试做什么:

如果你能够说服任何你需要的人并开始使用类似 ItemsControl 的东西, 这会简单得多。

说个粗略的例子:

xaml 可以是:

<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

Items声明为 public ObservableCollection<Rectangle> Items { get; set; }在代码中。

现在您的 Add()函数可以是:

private void Add() {
var rect = new Rectangle {
Stroke = Brushes.Red,
StrokeThickness = 1,
Height = Convert.ToDouble(txtheight.Text),
Width = 100
};
Items.Add(rect);
}

以及在您编辑现有控件时的更新,在这种情况下会自动进行。没有硬编码定位,因为 Layout 容器会为您处理所有这些乱七八糟的事情。

您当然可以切换 Items集合类型到您自己的自定义控件类型MyLayer并且随着它实现 INPC,更改仍然会继续自动进行。你必须定义一个 DataTemplate现在让你的项目被呈现,但这就像在 xaml 中的 3 行工作。

你也可以只工作Items在需要调整现有控件时直接访问属性,而不是必须引用 ItemsControl在代码隐藏中。绑定(bind)应该自动处理 View 的更新。

关于c# - 修改wpf中任何矩形的高度后如何在 Canvas 上重新排列矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17654270/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com