0

I have two instances of a Rectangle, I want to copy the attributes of one to another, but the code below results in changes to the copy affecting the original.

I believe I need to perform a deep copy of the Original Rectangle to avoid this behavior, but how can I do this?

C# WPF Application.

using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            SpecialButton tmp = new SpecialButton();
            tmp.Update();
        }

        public class SpecialButton
        {
            public Rectangle Original_Properties { get; set; }
            public Rectangle Copy_Properties { get; set; }

            public void Update()
            {
                Original_Properties = new Rectangle();
                Copy_Properties = new Rectangle();

                Original_Properties.StrokeThickness = 1;
                Original_Properties.Stroke = Brushes.White;
                Original_Properties.Width = 20;
                Original_Properties.Height = 20;
                Original_Properties.Tag = "exampleTag";

                Copy_Properties = Original_Properties; // this needs to be a deep copy i think.

                Copy_Properties.Width = Copy_Properties.Width / 2;
                Copy_Properties.Height = Copy_Properties.Height / 2;
                Copy_Properties.StrokeThickness = 2;
                Copy_Properties.Tag = Original_Properties.Tag + "_selected" ;
            }
        }
    }
}
AlexS
  • 510
  • 2
  • 7
  • 23
  • 1
    Just drop the line `Copy_Properties = Original_Properties;` and write `Copy_Properties.Width = Original_Properties.Width;` etc. – Clemens Feb 01 '19 at 17:29
  • Can you use for the rectangle struct value type? If so you won't need any deep copy there. – mexanichp Feb 01 '19 at 17:30
  • 1
    @clemens Good point - but the example I posted is a short version of the code to demonstrate the issue. Id rather avoid explicitly writing a function to copy the attributes item by item. – AlexS Feb 01 '19 at 17:32
  • There is no other way. It is however unclear why you need to do this at all. In WPF you usually do not create UI elements in code behind. – Clemens Feb 01 '19 at 17:33
  • @mexanich i don't think so, that appears to be windows forms? – AlexS Feb 01 '19 at 17:36
  • @Clemens i want the ability to create stylized buttons at arbitrary locations at run time using the .MouseDown property to assign the callback function at run-time. – AlexS Feb 01 '19 at 17:39
  • 2
    Do you really need a deep clone (recreating all the properties that are a reference type of this shape)? Maybe a regular cone would be enough, have you tried using the `MemberwiseClone()`? – IPValverde Feb 01 '19 at 17:41
  • @IPValverde I haven't - looks interesting - do you think you could give an example of it in this context? – AlexS Feb 01 '19 at 17:46
  • A "styled Button at runtime at arbitrary locations" is not at all a reason to create UI elements in code behind. Take a look at [Data Templating Overview](https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview). An example is here: https://stackoverflow.com/questions/22324359/add-n-rectangles-to-canvas-with-mvvm-in-wpf/22325266#22325266 – Clemens Feb 01 '19 at 17:56
  • @Clemens alas that looks useful, but a particularly steep learning curve for someone like myself. – AlexS Feb 01 '19 at 18:08
  • Sooner or later you'll have to learn these things anyway. Why not now? Without that knowledge you won't be able to leverage the full power of WPF. – Clemens Feb 01 '19 at 18:10
  • @clemens true - but unfortunately time pressure mean i need to get something working now rather than after I've learned a new way of thinking. I didn't think adding rectangles to a canvas would be so convoluted. – AlexS Feb 01 '19 at 18:16
  • @clemens i decided to bite the bullet and try to create the multiple button the proper XAML way. https://stackoverflow.com/questions/54494370/is-there-a-way-to-change-a-rectangles-color-in-xaml-using-changes-to-the-underly – AlexS Feb 02 '19 at 15:17

1 Answers1

0

Deep copying a wpf UI it's very simple if you don't need to keep value source of any dependency property. XamlWriter.Save(objcet) and XamlReader.Parse(string) will do that for you.

var btn1 = new Button() { Content = "click me" };
var btn2 = (Button)XamlReader.Parse(XamlWriter.Save(btn1));
Alex.Wei
  • 1,798
  • 6
  • 12