I am developing an add-in for OneNote.
In the sinppet below, a global variable AllPageXML is claimed first.
Then the very first time when a window is loaded, AllPageXML is initinized with a value.
After that, the value of AllPageXML is supposed to not be changed.
When the user input some keywords in a textbox, search in AllPageXML will be excuted.
And AllPageXML will be passed to an function FilterXml. After returnning, the value of AllPageXML has been changed.
How can I do to keep the value of AllPageXML not changed? Any comments will be appreciated.
internal partial class NaviPages : LocalizableForm
{
public XElement AllPageXML;
public NaviPages()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
using var one = new OneNote();
var AllPageXML = one.GetAllPages();
//...//
}
private void tBoxKw_TextChanged(object sender, EventArgs e)
{
try
{
string strKeyWords = tBoxKw.Text.ToLower();
FilteredPageXml = FilterXml(AllPageXML, strKeyWords);
}
catch
{
MessageBox.Show("Failed to filter!");
}
}
public XElement FilterXml(XElement inXML, string strKeyWords)
{
string strSecKw, strPageKw;
XElement root = inXML;
///...///
//delete empty notebook
foreach (var child1 in root.Elements().Reverse())
{
if (!child1.HasElements) child1.Remove();
}
return root;
}
}
Also, I've tried to use the ICloneable class to clone the AllPageXML before using it.
namespace OneNoteAddIn
{
internal partial class NaviPages : LocalizableForm
{
public NaviPages()
{
InitializeComponent();
}
public MyPages xml1;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
using var one = new OneNote();
xml1= new MyPages();
xml1.AllPageXML= one.GetAllPages();
}
public XElement FilterXml(XElement inXML, string strKeyWords)
{
XElement root = inXML; // xml2.AllPageXML;
//delete empty notebook
foreach (var child1 in root.Elements().Reverse())
{
if (!child1.HasElements) child1.Remove();
}
return root;
}
private void tBoxKw_TextChanged(object sender, EventArgs e)
{
XElement FilteredPageXml;
MyPages xml2 = new MyPages();
xml2 = (MyPages)xml1.Clone();
XElement AllPageXML1 = xml2.AllPageXML;
try
{
string strKeyWords = tBoxKw.Text.ToLower();
FilteredPageXml = FilterXml(AllPageXML1, strKeyWords);
}
catch
{
MessageBox.Show("Failed to filter!");
}
}
}
class MyPages : ICloneable
{
public XElement AllPageXML;
public object Clone()
{
return this.MemberwiseClone();
}
}
}
The line
XElement root = inXML;does not create a new object, it only sets the reference ofrootto the same referenceinXMLuses. So any changes torootorinXMLwill change the same object in memory. You should instead clone the object (create a new one with the same values). This can be done in 2 places.FilterXmlmethod.tBoxKw_TextChangedbeforeFilterXmlis called and passFilterXmlthe clone.To clone an object you should create a new object (using
new XElement()) and set the properties of that element to the values of properties of the object you wish to clone (AllPageXML). You could look into theICloneableinterface: https://learn.microsoft.com/en-us/dotnet/api/system.icloneable.clone?view=net-7.0