Owl's Blog on .NET development

Component Owl codes Better ListView control all night so you don't have to.

How to Store Better ListView Content in a String (User Request)

Is it possible to store entire Better ListView content (items with hierarchy and sub-items, columns and groups) in a single string?

Better ListView already supports saving and loading its content using SaveContent and LoadContent methods. These methods support either XML or binary format.

I chose binary format for storing data in string  because it is more compact than XML. Binary representation (basically an array of bytes) can be converted to Base64 string. Loading the content from string work similarly, the steps are performed in opposite direction:

C#

[csharp gutter=”false” toolbar=”false”]
// SAVE
// create MemoryStream to hold binary data
MemoryStream stream = new MemoryStream();
// store Better ListView content in memory stream
this.listView.SaveContentBinary(stream);
// copy content of MemoryStream to byte array
byte[] contentBinary = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
// convert byte array to Base64 string
stream.Read(contentBinary, 0, (int)stream.Length); // move to beginning of the stream
string contentStringBase64 = Convert.ToBase64String(contentBinary);
// close stream
stream.Close();
stream.Dispose();

// CLEAR
this.listView.Clear();

// LOAD
// create MemoryStream to hold binary data
stream = new MemoryStream();
// convert Base64 string to byte array
contentBinary = Convert.FromBase64String(contentStringBase64);
// write byte array to stream
stream.Write(contentBinary, 0, contentBinary.Length);
stream.Seek(0, SeekOrigin.Begin); // move to beginning of the stream
// load content of Better ListView from memory stream
this.listView.LoadContentBinary(stream);
[/csharp]

Visual Basic

[vb gutter=”false” toolbar=”false”]
‘ SAVE
‘ create MemoryStream to hold binary data
Dim stream As New MemoryStream()
‘ store Better ListView content in memory stream
Me.listView.SaveContentBinary(stream)
‘ copy content of MemoryStream to byte array
Dim contentBinary As Byte() = New Byte(stream.Length – 1) {}
stream.Seek(0, SeekOrigin.Begin)
‘ convert byte array to Base64 string
stream.Read(contentBinary, 0, CInt(stream.Length))
‘ move to beginning of the stream
Dim contentStringBase64 As String = Convert.ToBase64String(contentBinary)
‘ close stream
stream.Close()
stream.Dispose()

‘ CLEAR
Me.listView.Clear()

‘ LOAD
‘ create MemoryStream to hold binary data
stream = New MemoryStream()
‘ convert Base64 string to byte array
contentBinary = Convert.FromBase64String(contentStringBase64)
‘ write byte array to stream
stream.Write(contentBinary, 0, contentBinary.Length)
stream.Seek(0, SeekOrigin.Begin)
‘ move to beginning of the stream
‘ load content of Better ListView from memory stream
Me.listView.LoadContentBinary(stream)
[/vb]

 

Although saving and loading data this way is convenient, please consider the following drawback:

  • Standard serialization mechanism of .NET is used for converting classes and structures to XML or binary representation – hence the serialized data may not be possible to deserialize on different version of Better ListView if any public members of the serialized class have been changed.
  • The generated string is very long (few kilobytes for just two items).
  • Lots of data are stored which are not related to content itself (e.g. item colors).
  • The serialized representation is considered read-only – any changes can cause problems with deserialization; if you really want flexible way of storing ListView content, consider building a model or data layer that supports storing the data you need the way you need.

On the other hand, using this way may be convenient when you want to transfer or copy ListView content between controls on even across application domain (Better ListView itself uses this mechanism to allow Drag and Drop between two applications – this “tour de force” kind of Drag and Drop is not avaiable in regular .NET ListView).

Leave a Reply