C# WPF画布子矩形框

C# WPF画布子矩形框,c#,wpf,canvas,C#,Wpf,Canvas,是否有任何方法可以创建一个画布副本,新画布将作为第一个画布的子元素框 第一张画布 第二张画布 我希望在第二个画布中显示类似的内容。您可以通过从画布派生并重写来实现这一点 您必须将更改公开,以便您复制的画布(我们称之为目标画布)可以正确更新 如果需要在源画布具有更新其属性的子级时侦听更改,那么要执行的操作相当复杂。在这种情况下,您必须再次将更改通知目标画布,这可以通过添加绑定来完成 XAML 在设计时,这是窗口: 特别注意VisualChildrenChanged=“CanvasSour

是否有任何方法可以创建一个画布副本,新画布将作为第一个画布的子元素框

第一张画布

第二张画布


我希望在第二个画布中显示类似的内容。

您可以通过从
画布
派生并重写来实现这一点

您必须将更改公开,以便您复制的
画布
(我们称之为目标
画布
)可以正确更新

如果需要在源画布具有更新其属性的子级时侦听更改,那么要执行的操作相当复杂。在这种情况下,您必须再次将更改通知目标画布,这可以通过添加绑定来完成

XAML

在设计时,这是窗口:

特别注意
VisualChildrenChanged=“CanvasSource\u VisualChildrenChanged”
。这就是这些变化是如何公开的。我们在
main窗口的代码隐藏中处理这些更改

可见的 最终结果 这是启动时的窗口。它具有目标
画布中元素的副本

由于我们在初始化后2秒发生了属性更改(请参见后面的代码),因此在更改发生后,下面是一个窗口:


我小时候有一个关于台词的答案,但我想要一个更好的解决方案

Point firstPoint = new Point(DrawCanvas.ActualWidth, DrawCanvas.ActualHeight);
Point endPoint = new Point(0, 0);
foreach (Line element in DrawCanvas.Children)
{

    double x = element.X1;
    double y = element.Y1;


    if (x < firstPoint.X)
        firstPoint.X = x;

    if (y < firstPoint.Y)
        firstPoint.Y = y;

    if (element.X2 > endPoint.X)
        endPoint.X = element.X2;

    if (element.Y2 > endPoint.Y)
        endPoint.Y = element.Y2;
}

double offsetX = firstPoint.X - 5;
double offsetY = firstPoint.Y - 5;


var children = DrawCanvas.Children.Cast<Line>().ToArray();
DrawCanvas.Children.Clear();

Rectangle rect = new Rectangle();
rect.Stroke = new SolidColorBrush(Color.FromRgb(0, 111, 0));
rect.Fill = new SolidColorBrush(Color.FromRgb(0, 111, 111));
rect.Width = endPoint.X - offsetX + 5;
rect.Height = endPoint.Y - offsetY + 5;
Canvas.SetLeft(rect, 0);
Canvas.SetTop(rect, 0);

newCanvas.Children.Add(rect);
newCanvas.Width = rect.Width;
newCanvas.Height = rect.Height;

foreach (Line element in children)
{
    Line newLine = element;
    newLine.X1 = element.X1 - offsetX;
    newLine.X2 = element.X2 - offsetX;
    newLine.Y1 = element.Y1 - offsetY;
    newLine.Y2 = element.Y2 - offsetY;

    newCanvas.Children.Add(newLine);
}
pointfirstpoint=新点(DrawCanvas.ActualWidth、DrawCanvas.ActualHeight);
点端点=新点(0,0);
foreach(DrawCanvas.Children中的Line元素)
{
双x=元素X1;
双y=元素1.Y1;
如果(xendPoint.X)
端点.X=元素.X2;
if(element.Y2>endPoint.Y)
端点.Y=元素.Y2;
}
双偏移量X=第一点X-5;
双偏置=第一点Y-5;
var children=DrawCanvas.children.Cast().ToArray();
DrawCanvas.Children.Clear();
矩形rect=新矩形();
Stroke=newsolidColorBrush(Color.FromRgb(0,111,0));
rect.Fill=新的SolidColorBrush(Color.FromRgb(0,111,111));
矩形宽度=端点X-偏移量X+5;
直线高度=端点Y-偏移量+5;
Canvas.SetLeft(rect,0);
Canvas.SetTop(rect,0);
newCanvas.Children.Add(rect);
newCanvas.Width=rect.Width;
newCanvas.Height=rect.Height;
foreach(子对象中的行元素)
{
换行符=元素;
换行符.X1=元素.X1-偏移量x;
newLine.X2=element.X2-offsetX;
换行符.Y1=元素.Y1-偏移;
newLine.Y2=element.Y2-offsetY;
newCanvas.Children.Add(换行符);
}

您需要什么有点不清楚。您是否需要两张画布,但其中一张(副本)包含第一张画布中孩子的副本?这两个画布的区别是什么?画布的大小和(每个子元素的canvas.top、canvas.left)如果我可以问的话,您打算用这些画布做什么?我已经实现了一个解决方案,但对它的实际用途很好奇。我不相信你的问题有一个简单的解决方案,除非用不同的方法解决这个问题。我喜欢你的答案,但它不适合我。我想在画布上画图,然后将“画图”移到第二个画布上,但只保留我有一些元素的区域,而不是空白区域。在这些图像上,我有背景色,所以你可以了解元素的位置。
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        //Demonstrate that children added from inside the code-behind are reflected.
        Rectangle newRectangle = new Rectangle() { Width = 50, Height = 50, Fill = Brushes.Orange };
        CanvasSource.Children.Add(newRectangle);
        Canvas.SetLeft(newRectangle, 100);
        Canvas.SetTop(newRectangle, 100);

        CanvasSource.PropertyChanged += CanvasSource_PropertyChanged;

        //Also, demonstrate that child property changes can be seen.
        DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) };
        timer.Tick += (sender, args) =>
        {
            timer.Stop();
            newRectangle.Fill = Brushes.Brown;
        };
        timer.Start();
    }

    //This event handler is called when a child is added to or removed from
    //the ObservableCanvas.
    private void CanvasSource_VisualChildrenChanged(object sender, RoutedEventArgs e)
    {
        ObservableCanvas source = sender as ObservableCanvas;
        if (source == null) return;
        CopyElements(source);
    }

    //This event handler is called when a child element of the ObservableCanvas
    //has a property that changes.
    void CanvasSource_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        ObservableCanvas source = sender as ObservableCanvas;
        if (source == null) return;
        CopyElements(source);
    }

    //This event handler is used to ensure that the target Canvas
    //has the elements copied from the source when initialized.
    private void CanvasTarget_Loaded(object sender, RoutedEventArgs e)
    {
        CopyElements(CanvasSource);
    }

    //This function creates a brand new copy of the ObservableCanvas's
    //children and puts it into the target Canvas.
    private void CopyElements(ObservableCanvas source)
    {
        if (CanvasTarget == null) return;

        CanvasTarget.Children.Clear();  //Start from scratch.
        foreach (UIElement child in source.Children)
        {
            //We need to create a deep clone of the elements to they copy.
            //This is necessary since we can't add the same child to two different
            //UIlements.
            UIElement clone = (UIElement)XamlReader.Parse(XamlWriter.Save(child));
            CanvasTarget.Children.Add(clone);
        }
    }
}
Point firstPoint = new Point(DrawCanvas.ActualWidth, DrawCanvas.ActualHeight);
Point endPoint = new Point(0, 0);
foreach (Line element in DrawCanvas.Children)
{

    double x = element.X1;
    double y = element.Y1;


    if (x < firstPoint.X)
        firstPoint.X = x;

    if (y < firstPoint.Y)
        firstPoint.Y = y;

    if (element.X2 > endPoint.X)
        endPoint.X = element.X2;

    if (element.Y2 > endPoint.Y)
        endPoint.Y = element.Y2;
}

double offsetX = firstPoint.X - 5;
double offsetY = firstPoint.Y - 5;


var children = DrawCanvas.Children.Cast<Line>().ToArray();
DrawCanvas.Children.Clear();

Rectangle rect = new Rectangle();
rect.Stroke = new SolidColorBrush(Color.FromRgb(0, 111, 0));
rect.Fill = new SolidColorBrush(Color.FromRgb(0, 111, 111));
rect.Width = endPoint.X - offsetX + 5;
rect.Height = endPoint.Y - offsetY + 5;
Canvas.SetLeft(rect, 0);
Canvas.SetTop(rect, 0);

newCanvas.Children.Add(rect);
newCanvas.Width = rect.Width;
newCanvas.Height = rect.Height;

foreach (Line element in children)
{
    Line newLine = element;
    newLine.X1 = element.X1 - offsetX;
    newLine.X2 = element.X2 - offsetX;
    newLine.Y1 = element.Y1 - offsetY;
    newLine.Y2 = element.Y2 - offsetY;

    newCanvas.Children.Add(newLine);
}