1

I want to save the current state of List<List<Button>> lloMatrix in an other variable List<List<Button>> lloMatrixCopy, create a Frame (a class i wrote) with it and add it to a list loFrames. lloMatrixCopy, as a property of the Frame, shall not change afterwards. I tried different ways, but my final List only lists equal lloMatrixCopy everytime, all identical to the latest Version of lloMatrix. So my question is how to make a copy of the current state of lloMatrix without it getting overwritten afterwards as soon as lloMatrix changes.

List<List<Button>> lloMatrixCopy = new List<List<Button>>;
List<List<Button>> lloMatrix = new List<List<Button>>;
List<Frame> loFrames = new List<Frame>;

//...
//lloMatrix gets filled with objects
//...

private void Btn_Click(object sender, RoutedEventArgs e)
{
   lloMatrixCopy = lloMatrix;
   var oNewFrame = new Frame(lloMatrixCopy);
   loFrames.Add(oNewFrame);
}

lloMatrix is getting changed afterwards, but loFrames shall only list it state at that Moment the button got pressed. I guess it's an easy question, but i tried many Things and it just doesn't work. Also sorry for not perfect english. I hope it's understandable.

EDIT: Thank you for fast Responses, but for some reasons

_lloMatrixCopy = _lloMatrixLeds.Select(original => original.ToList()).ToList();

also doesn't solve the Problem. Here the full Btn_Click()-Method

private void Btn_Click(object sender, RoutedEventArgs e)
        {
            lloMatrixCopy = lloMatrix.Select(original => original.ToList()).ToList();
            var oNewFrame = new Frame(lloMatrixCopy);
            loFrames.Add(oNewFrame);

//After adding the copy to the list i want to put lloMatrix back in Default
//mode - which means in my case Change the Background Color of every Button to a specific Default
//Color. but the foreach-loop doenst only Change the lloMatrix, but also the
//copy, so that every Matrix saved in loFrames is a Default Matrix
// Globals.LClickedButtons is a list of every Button in lloMatrix which Background-Color
// isn't equal to the Default-Color
            foreach (var btn in Globals.LClickedButtons)
            {
                btn.Background = loLedColorBrushes[0];             
            }
        }

Every Matrix in loFrames still is a default Matrix as soon as the foreach-loop is done.

Kunibert
  • 21
  • 8
  • have you updated `lloMatrix` with the state values before pressing the update? –  May 30 '17 at 11:47
  • Sorry, I'm not too sure about what you mean, i update `lloMatrix` right after i made the copy and added it to the list. Please have a look at the edited question – Kunibert May 30 '17 at 12:26
  • The Button instances don't get copied just because you create another List – mm8 May 30 '17 at 12:33

3 Answers3

1

this will make a deep copy

using System.Windows.Markup;
using System.Xml;
using System.IO;

T CloneXaml(T source){
    string xaml = XamlWriter.Save(T);
    using (StringReader stringReader = new StringReader(xaml))
    using (xmlReader = XmlReader.Create(stringReader))
        return (T)XamlReader.Load(xmlReader);
}


lloMatrixCopy = lloMatrix.Select( inner => inner.ToList().Select(CloneXaml)).ToList();

You need to understand that List<T> is a reference type.

There are two kinds of types in C#: reference types and value types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data. With reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable. With value types, each variable has its own copy of the data, and it is not possible for operations on one variable to affect the other (except in the case of ref and out parameter variables, see ref and out parameter modifier).

bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
0

This

lloMatrixCopy = lloMatrix; 

Simply creates a second reference to each of the items in the list so if you modify an item in one of the lists the corresponding item in the other list gets modified too.

You need to duplicate each item in the list and put it into your second list. Something like this will work

lloMatrixCopy = lloMatrix.Select(original => original.ToList()).ToList();
Gareth
  • 913
  • 6
  • 14
  • thank you for your fast answer! For some reason it's still not working properly. Could you have an other look at my edited question? – Kunibert May 30 '17 at 12:28
0

You need to clone each of individual the Button elements. The easiest way to clone a WPF element is to use the XamlWriter.Save and XamlReader.Load methods as suggested here:

How can you clone a WPF object?

The following only creates a copy of the List<Button>:

_lloMatrixCopy = _lloMatrixLeds.Select(original => original.ToList()).ToList();

Both lists will still hold references to the very same Button elements.

So you need to do something like this to clone the actual Button elements:

foreach (var btn in Globals.LClickedButtons)
{
    string xaml = System.Windows.Markup.XamlWriter.Save(btn);

    using (System.IO.StringReader stringReader = new System.IO.StringReader(xaml))
    {
        using (System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader))
        {
            Button newButton = (Button)System.Windows.Markup.XamlReader.Load(xmlReader);
            //...
        }
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88