How do I copy a TreeViewItem onto another that is using an object as a tag and header?
Question
I have a TreeViewItem where I am using a TextBlock for the Header property and a custom class as the Tag property. How do I go about creating a copy of the TreeViewItem? I've tried serializing it, but it keeps going into an infinite loop, creates a Stack OverFlow Exception, when it tries to serialize the TreeViewItem, but I can't find out where.
This is the custom class I am using as a Tag property for my TreeViewItem
[Serializable]
[XmlRoot(ElementName="TVITagProperty")]
public class TVITagProperty {
#region Members
/// <summary>
/// Tree Type
/// </summary>
public enum TreeType {
User = 1,
Other = 2,
}
/// <summary>
/// Tag Property Type
/// </summary>
public enum TagType {
Entity = 1,
User = 2,
};
#endregion
#region C'tor
/// <summary>
/// Public parameterless constructor
/// </summary>
public TVITagProperty() { }
/// <summary>
/// Create a TreeViewItem Tag Property
/// </summary>
/// <param name="type">Type of Tag Property</param>
/// <param name="value">Value of Tag Property</param>
public TVITagProperty(TreeType treeType, TagType tagType, string value) {
ViewType = treeType;
PropertyType = tagType;
PropertyValue = value;
PropertyDirectory = false;
}
/// <summary>
/// Create a TreeViewItem Tag Property
/// </summary>
/// <param name="type">Type of Tag Property</param>
/// <param name="value">Value of Tag Property</param>
public TVITagProperty(TagType type, long? value) {
PropertyType = type;
PropertyValue = value.ToString();
}
#endregion
#region Methods
/// <summary>
/// Overloaded Equals method, compares one TVI Tag Property Property Type and Value
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool Equals(TVITagProperty obj) {
if(obj != null) {
if(obj.PropertyDirectory == true) {
if(this.ViewType == obj.ViewType &&
this.PropertyType == obj.PropertyType) {
return true;
}
}
else if(this.ViewType == obj.ViewType &&
this.PropertyType == obj.PropertyType &&
this.PropertyValue.Equals(obj.PropertyValue)) {
return true;
}
}
return false;
}
/// <summary>
/// Overrides ToString() and returns Property value
/// </summary>
/// <returns></returns>
public override string ToString() {
return this.PropertyValue;
}
/// <summary>
/// Returns the Property value as a long
/// </summary>
/// <returns></returns>
public long ToLong() {
return long.Parse(this.PropertyValue);
}
#endregion
#region Properties
/// <summary>
/// Represents the type of TreeView used in the View
/// </summary>
[XmlAttribute]
public TreeType ViewType { get; set; }
/// <summary>
/// The type of Property Tag
/// </summary>
[XmlAttribute]
public TagType PropertyType { get; set; }
/// <summary>
/// The value of Property Tag
/// </summary>
[XmlAttribute]
public string PropertyValue { get; set; }
/// <summary>
/// Defines whether the TVI is an object or directory
/// </summary>
[XmlAttribute]
public bool PropertyDirectory { get; set; }
#endregion
}
Solution
Creating a copy of a wpf TreeViewItem seems like the wrong approach - why do you want to do that?
A better way is to not generate any treeviewitems yourself but let wpf handle it via a hierachical template and itemsource -then you can make copies of your objects in your itemssource and wpf will render them for you.
see for example this:
OTHER TIPS
There is a good deep clone object on codeproject here
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
More references and discussion posted here