|
using System;
using System.Collections;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Collections.Generic;
namespace Personalisation
{
/// <summary>
/// Handles the configuration and personalisation of a list view
/// </summary>
public class ListViewPersonalisationManager
{
private ColumnDetails[] columnDetails;
/// <summary>
/// Gets or sets the column details.
/// </summary>
/// <value>The column details.</value>
public ColumnDetails[] ColumnDetails
{
get{return columnDetails;}
set{columnDetails = value;}
}
private ListView listView;
private Dictionary<ColumnHeader, int> columnIndex;
private Dictionary<int, ColumnHeader> positionIndex;
private string settingsFileName;
/// <summary>
/// Initializes a new instance of the <see cref="ListViewPersonalisationManager"/> class.
/// </summary>
/// <param name="listView">The list view to personalise.</param>
public ListViewPersonalisationManager(ListView listView): this(listView, Guid.Empty, new List<string>())
{}
/// <summary>
/// Initializes a new instance of the <see cref="ListViewPersonalisationManager"/> class.
/// </summary>
/// <remarks>If the specified identifier is Guid.Empty then the details will not be persisted</remarks>
/// <param name="listView">The list view to personalise.</param>
/// <param name="identifier">An unique identifier associated with the ListView which will be used to store the information.</param>
public ListViewPersonalisationManager(ListView listView, Guid identifier) : this(listView, identifier, new List<string>())
{}
/// <summary>
/// Initializes a new instance of the <see cref="ListViewPersonalisationManager"/> class.
/// </summary>
/// <remarks>If the specified identifier is Guid.Empty then the details will not be persisted</remarks>
/// <param name="listView">The list view to personalise.</param>
/// <param name="identifier">An unique identifier associated with the ListView which will be used to store the information.</param>
/// <param name="requiredColumns">Any columns that must always be displayed.</param>
public ListViewPersonalisationManager(ListView listView, Guid identifier, List<string> requiredColumns)
{
// Keep a handle on the ListView
this.listView = listView;
// Initialise the variables
columnIndex = new Dictionary<ColumnHeader, int>();
positionIndex = new Dictionary<int, ColumnHeader>();
if(listView != null)
{
for(int j = listView.Columns.Count - 1; j >=0; j--)
{
columnIndex.Add(listView.Columns[j], j);
positionIndex.Add(j, listView.Columns[j]);
}
}
// Set the Isolated storage file name.
if(identifier != Guid.Empty)
settingsFileName = string.Format(CultureInfo.InvariantCulture,"LV{0}.dat", identifier.ToString("N",CultureInfo.InvariantCulture));
else
settingsFileName = string.Empty;
// If there are previously stored setting restore the ListView from them
if(!ReadSettings())
InitialiseFromListView(requiredColumns);
}
/// <summary>
/// Initialises the ColumnDetails collection from the current state of the ListView
/// </summary>
/// <param name="requiredColumns">The columns that must always be displayed</param>
private void InitialiseFromListView(List<string> requiredColumns)
{
columnDetails = new ColumnDetails[listView.Columns.Count];
int i=0;
foreach(ColumnHeader column in listView.Columns)
{
columnDetails[i].PreferredCaption = column.Text;
columnDetails[i].Name = column.Text;
columnDetails[i].InitialIndex = i;
columnDetails[i].Position = i;
columnDetails[i].Width = column.Width;
columnDetails[i].Show = true;
columnDetails[i].Alignment = 0;
columnDetails[i++].Required = requiredColumns.Contains(column.Text);
}
}
private const int LVM_FIRST=0x1000;
private const int LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58;
private const int LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59;
/// <summary>
/// Updates the ListView based on the supplied new ColumnDetails
/// </summary>
/// <param name="newDetails">The new column details</param>
public void UpdateListView(ColumnDetails[] newDetails)
{
listView.BeginUpdate();
int count = listView.Columns.Count;
int[] columnPositions = new int[count];
for(int i = count - 1; i >=0; i--)
{
// Rearrangle the columns
columnPositions[newDetails[i].Position] = newDetails[i].InitialIndex;
if(!newDetails[i].Show)
listView.Columns[i].Width = 0;
else
{
listView.Columns[i].Width = newDetails[i].Width;
listView.Columns[i].Text = newDetails[i].PreferredCaption;
}
}
// Reorder the column positions, unfortunately we need to resort to Windows API calls to achieve this.
NativeMethods.SendMessage( listView.Handle, LVM_SETCOLUMNORDERARRAY, count, columnPositions );
listView.EndUpdate();
columnDetails = newDetails;
}
/// <summary>
/// Gets the current order of the ListView's columns.
/// </summary>
/// <returns></returns>
private int[] GetColumnOrder()
{
int[] orders = new int[listView.Columns.Count];
int ret = NativeMethods.SendMessage(listView.Handle, LVM_GETCOLUMNORDERARRAY, orders.Length, orders);
if (ret > 0)
return orders;
throw new Exception("GetColumnOrder failed");
}
/// <summary>
/// Synchronises the current ListView settings held details
/// </summary>
public void SyncWithListView()
{
// Position
int[] currentOrder = GetColumnOrder();
for(int i = 0; i < currentOrder.Length; i++)
columnDetails[currentOrder[i]].Position = i;
// Width
foreach(ColumnHeader column in listView.Columns )
{
int initialIndex = (int)columnIndex[column];
for(int i = columnDetails.Length - 1; i >=0; i--)
{
if((initialIndex == columnDetails[i].InitialIndex) && (columnDetails[i].Show))
columnDetails[i].Width = column.Width;
}
}
}
/// <summary>
/// Saves the current ListView settings to Isolated storage.
/// </summary>
/// <param name="synchroniseFirst">if set to <c>true</c> synchronise with the current state of the ListView first.</param>
/// <returns>
/// True if the details are saved successfully
/// </returns>
public bool SaveSettings(bool synchroniseFirst)
{
if(synchroniseFirst)
SyncWithListView();
return Utilities.SerialiseToIsolatedStorage(settingsFileName, columnDetails);
}
/// <summary>
/// Reads the last saved settings from IsolatedStorage
/// </summary>
/// <returns>True if the settings were read successfully</returns>
public bool ReadSettings()
{
ColumnDetails[] savedDetails = Utilities.DeserialiseFromIsolatedStorage<ColumnDetails[]>(settingsFileName, new ColumnDetailsDeserialisationBinder());
if(savedDetails != null)
{
UpdateListView(savedDetails);
return true;
}
else
return false;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.